Browse Source

Merge branch 'master' of orgmode.org:org-mode

Bastien Guerry 12 years ago
parent
commit
f72bb5733d

+ 47 - 22
contrib/lisp/org-e-ascii.el

@@ -104,23 +104,23 @@
   :menu-entry
   (?t "Export to Plain Text"
       ((?A "As ASCII buffer"
-	   (lambda (s v b)
-	     (org-e-ascii-export-as-ascii s v b '(:ascii-charset ascii))))
+	   (lambda (a s v b)
+	     (org-e-ascii-export-as-ascii a s v b '(:ascii-charset ascii))))
        (?a "As ASCII file"
-	   (lambda (s v b)
-	     (org-e-ascii-export-to-ascii s v b '(:ascii-charset ascii))))
+	   (lambda (a s v b)
+	     (org-e-ascii-export-to-ascii a s v b '(:ascii-charset ascii))))
        (?L "As Latin1 buffer"
-	   (lambda (s v b)
-	     (org-e-ascii-export-as-ascii s v b '(:ascii-charset latin1))))
+	   (lambda (a s v b)
+	     (org-e-ascii-export-as-ascii a s v b '(:ascii-charset latin1))))
        (?l "As Latin1 file"
-	   (lambda (s v b)
-	     (org-e-ascii-export-to-ascii s v b '(:ascii-charset latin1))))
+	   (lambda (a s v b)
+	     (org-e-ascii-export-to-ascii a s v b '(:ascii-charset latin1))))
        (?U "As UTF-8 buffer"
-	   (lambda (s v b)
-	     (org-e-ascii-export-as-ascii s v b '(:ascii-charset utf-8))))
+	   (lambda (a s v b)
+	     (org-e-ascii-export-as-ascii a s v b '(:ascii-charset utf-8))))
        (?u "As UTF-8 file"
-	   (lambda (s v b)
-	     (org-e-ascii-export-to-ascii s v b '(:ascii-charset utf-8))))))
+	   (lambda (a s v b)
+	     (org-e-ascii-export-to-ascii a s v b '(:ascii-charset utf-8))))))
   :filters-alist ((:filter-headline . org-e-ascii-filter-headline-blank-lines)
 		  (:filter-parse-tree . org-e-ascii-filter-paragraph-spacing)
 		  (:filter-section . org-e-ascii-filter-headline-blank-lines))
@@ -1780,7 +1780,7 @@ This function only applies to `e-ascii' back-end.  See
 
 ;;;###autoload
 (defun org-e-ascii-export-as-ascii
-  (&optional subtreep visible-only body-only ext-plist)
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to a text buffer.
 
 If narrowing is active in the current buffer, only export its
@@ -1788,6 +1788,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting buffer should be accessible
+through the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -1806,16 +1810,27 @@ Export is done in a buffer named \"*Org E-ASCII Export*\", which
 will be displayed when `org-export-show-temporary-export-buffer'
 is non-nil."
   (interactive)
-  (let ((outbuf (org-export-to-buffer
-		 'e-ascii "*Org E-ASCII Export*"
-		 subtreep visible-only body-only ext-plist)))
-    (with-current-buffer outbuf (text-mode))
-    (when org-export-show-temporary-export-buffer
-      (switch-to-buffer-other-window outbuf))))
+  (if async
+      (org-export-async-start
+	  (lambda (output)
+	    (with-current-buffer (get-buffer-create "*Org E-ASCII Export*")
+	      (erase-buffer)
+	      (insert output)
+	      (goto-char (point-min))
+	      (text-mode)
+	      (org-export-add-to-stack (current-buffer) 'e-ascii)))
+	`(org-export-as 'e-ascii ,subtreep ,visible-only ,body-only
+			',ext-plist))
+    (let ((outbuf (org-export-to-buffer
+		   'e-ascii "*Org E-ASCII Export*"
+		   subtreep visible-only body-only ext-plist)))
+      (with-current-buffer outbuf (text-mode))
+      (when org-export-show-temporary-export-buffer
+	(switch-to-buffer-other-window outbuf)))))
 
 ;;;###autoload
 (defun org-e-ascii-export-to-ascii
-  (&optional subtreep visible-only body-only ext-plist)
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to a text file.
 
 If narrowing is active in the current buffer, only export its
@@ -1823,6 +1838,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting file should be accessible through
+the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -1840,8 +1859,14 @@ file-local settings.
 Return output file's name."
   (interactive)
   (let ((outfile (org-export-output-file-name ".txt" subtreep)))
-    (org-export-to-file
-     'e-ascii outfile subtreep visible-only body-only ext-plist)))
+    (if async
+	(org-export-async-start
+	    (lambda (f) (org-export-add-to-stack f 'e-ascii))
+	  `(expand-file-name
+	    (org-export-to-file
+	     'e-ascii ,outfile ,subtreep ,visible-only ,body-only ',ext-plist)))
+      (org-export-to-file
+       'e-ascii outfile subtreep visible-only body-only ext-plist))))
 
 ;;;###autoload
 (defun org-e-ascii-publish-to-ascii (plist filename pub-dir)

+ 57 - 15
contrib/lisp/org-e-beamer.el

@@ -273,8 +273,9 @@ brackets.  Return overlay specification, as a string, or nil."
        (?b "As TEX file (Beamer)" org-e-beamer-export-to-latex)
        (?P "As PDF file (Beamer)" org-e-beamer-export-to-pdf)
        (?O "As PDF file and open (Beamer)"
-	   (lambda (s v b)
-	     (org-open-file (org-e-beamer-export-to-pdf s v b))))))
+	   (lambda (a s v b)
+	     (if a (org-e-beamer-export-to-pdf t s v b)
+	       (org-open-file (org-e-beamer-export-to-pdf nil s v b)))))))
   :options-alist
   ((:beamer-theme "BEAMER_THEME" nil org-e-beamer-theme)
    (:beamer-color-theme "BEAMER_COLOR_THEME" nil nil t)
@@ -980,7 +981,7 @@ value."
 
 ;;;###autoload
 (defun org-e-beamer-export-as-latex
-  (&optional subtreep visible-only body-only ext-plist)
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer as a Beamer buffer.
 
 If narrowing is active in the current buffer, only export its
@@ -988,6 +989,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting buffer should be accessible
+through the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -1006,16 +1011,28 @@ Export is done in a buffer named \"*Org E-BEAMER Export*\", which
 will be displayed when `org-export-show-temporary-export-buffer'
 is non-nil."
   (interactive)
-  (let ((outbuf (org-export-to-buffer
-		 'e-beamer "*Org E-BEAMER Export*"
-		 subtreep visible-only body-only ext-plist)))
-    (with-current-buffer outbuf (LaTeX-mode))
-    (when org-export-show-temporary-export-buffer
-      (switch-to-buffer-other-window outbuf))))
+  (if async
+      (org-export-async-start
+	  (lambda (output)
+	    (with-current-buffer (get-buffer-create "*Org E-BEAMER Export*")
+	      (erase-buffer)
+	      (insert output)
+	      (goto-char (point-min))
+	      (LaTeX-mode)
+	      (when org-export-show-temporary-export-buffer
+		(org-export-add-to-stack (current-buffer) 'e-beamer))))
+	`(org-export-as 'e-beamer ,subtreep ,visible-only ,body-only
+			',ext-plist))
+    (let ((outbuf (org-export-to-buffer
+		   'e-beamer "*Org E-BEAMER Export*"
+		   subtreep visible-only body-only ext-plist)))
+      (with-current-buffer outbuf (LaTeX-mode))
+      (when org-export-show-temporary-export-buffer
+	(switch-to-buffer-other-window outbuf)))))
 
 ;;;###autoload
 (defun org-e-beamer-export-to-latex
-  (&optional subtreep visible-only body-only ext-plist)
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer as a Beamer presentation (tex).
 
 If narrowing is active in the current buffer, only export its
@@ -1023,6 +1040,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting file should be accessible through
+the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -1040,12 +1061,19 @@ file-local settings.
 Return output file's name."
   (interactive)
   (let ((outfile (org-export-output-file-name ".tex" subtreep)))
-    (org-export-to-file
-     'e-beamer outfile subtreep visible-only body-only ext-plist)))
+    (if async
+	(org-export-async-start
+	    (lambda (f) (org-export-add-to-stack f 'e-beamer))
+	  `(expand-file-name
+	    (org-export-to-file
+	     'e-beamer ,outfile ,subtreep ,visible-only ,body-only
+	     ',ext-plist)))
+      (org-export-to-file
+       'e-beamer outfile subtreep visible-only body-only ext-plist))))
 
 ;;;###autoload
 (defun org-e-beamer-export-to-pdf
-  (&optional subtreep visible-only body-only ext-plist)
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer as a Beamer presentation (PDF).
 
 If narrowing is active in the current buffer, only export its
@@ -1053,6 +1081,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting file should be accessible through
+the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -1069,8 +1101,18 @@ file-local settings.
 
 Return PDF file's name."
   (interactive)
-  (org-e-latex-compile
-   (org-e-beamer-export-to-latex subtreep visible-only body-only ext-plist)))
+  (if async
+      (let ((outfile (org-export-output-file-name ".tex" subtreep)))
+	(org-export-async-start
+	    (lambda (f) (org-export-add-to-stack f 'e-beamer))
+	  `(expand-file-name
+	    (org-e-latex-compile
+	     (org-export-to-file
+	      'e-beamer ,outfile ,subtreep ,visible-only ,body-only
+	      ',ext-plist)))))
+    (org-e-latex-compile
+     (org-e-beamer-export-to-latex
+      nil subtreep visible-only body-only ext-plist))))
 
 ;;;###autoload
 (defun org-e-beamer-select-environment ()

+ 38 - 9
contrib/lisp/org-e-groff.el

@@ -100,7 +100,9 @@
       ((?g "As GROFF file" org-e-groff-export-to-groff)
        (?p "As PDF file" org-e-groff-export-to-pdf)
        (?o "As PDF file and open"
-	   (lambda (s v b) (org-open-file (org-e-groff-export-to-pdf s v b))))))
+	   (lambda (a s v b)
+	     (if a (org-e-groff-export-to-pdf t s v b)
+	       (org-open-file (org-e-groff-export-to-pdf nil s v b)))))))
   :options-alist
   ((:groff-class "GROFF_CLASS" nil org-e-groff-default-class t)
    (:groff-class-options "GROFF_CLASS_OPTIONS" nil nil t)
@@ -1886,7 +1888,7 @@ contextual information."
 ;;; Interactive functions
 
 (defun org-e-groff-export-to-groff
-  (&optional subtreep visible-only body-only ext-plist)
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to a Groff file.
 
 If narrowing is active in the current buffer, only export its
@@ -1894,6 +1896,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting file should be accessible through
+the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -1907,14 +1913,23 @@ file-local settings.
 
 Return output file's name."
   (interactive)
-  (setq org-e-groff-registered-references nil)
-  (setq org-e-groff-special-content nil)
   (let ((outfile (org-export-output-file-name ".groff" subtreep)))
-    (org-export-to-file
-     'e-groff outfile subtreep visible-only body-only ext-plist)))
+    (if async
+	(org-export-async-start
+	    (lambda (f) (org-export-add-to-stack f 'e-groff))
+	  (let ((org-e-groff-registered-references nil)
+		(org-e-groff-special-content nil))
+	    `(expand-file-name
+	      (org-export-to-file
+	       'e-groff ,outfile ,subtreep ,visible-only ,body-only
+	       ',ext-plist))))
+      (let ((org-e-groff-registered-references nil)
+	    (org-e-groff-special-content nil))
+	(org-export-to-file
+	 'e-groff outfile subtreep visible-only body-only ext-plist)))))
 
 (defun org-e-groff-export-to-pdf
-  (&optional subtreep visible-only body-only ext-plist)
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to Groff then process through to PDF.
 
 If narrowing is active in the current buffer, only export its
@@ -1922,6 +1937,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting file should be accessible through
+the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -1935,8 +1954,18 @@ file-local settings.
 
 Return PDF file's name."
   (interactive)
-  (org-e-groff-compile
-   (org-e-groff-export-to-groff subtreep visible-only body-only ext-plist)))
+  (if async
+      (let ((outfile (org-export-output-file-name ".groff" subtreep)))
+	(org-export-async-start
+	    (lambda (f) (org-export-add-to-stack f 'e-groff))
+	  `(expand-file-name
+	    (org-e-groff-compile
+	     (org-export-to-file
+	      'e-groff ,outfile ,subtreep ,visible-only ,body-only
+	      ',ext-plist)))))
+    (org-e-groff-compile
+     (org-e-groff-export-to-groff
+      nil subtreep visible-only body-only ext-plist))))
 
 (defun org-e-groff-compile (file)
   "Compile a Groff file.

+ 41 - 13
contrib/lisp/org-e-html.el

@@ -108,7 +108,9 @@
       ((?H "To temporary buffer" org-e-html-export-as-html)
        (?h "To file" org-e-html-export-to-html)
        (?o "To file and open"
-	   (lambda (s v b) (org-open-file (org-e-html-export-to-html s v b))))))
+	   (lambda (a s v b)
+	     (if a (org-e-html-export-to-html t s v b)
+	       (org-open-file (org-e-html-export-to-html nil s v b)))))))
   :options-alist
   ;; FIXME: Prefix KEYWORD and OPTION with "HTML_".  Prefix
   ;; corresponding properties with `:html-".  If such a renaming is
@@ -2746,7 +2748,7 @@ contextual information."
 
 ;;;###autoload
 (defun org-e-html-export-as-html
-  (&optional subtreep visible-only body-only ext-plist)
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to an HTML buffer.
 
 If narrowing is active in the current buffer, only export its
@@ -2754,6 +2756,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting buffer should be accessible
+through the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -2772,18 +2778,28 @@ Export is done in a buffer named \"*Org E-HTML Export*\", which
 will be displayed when `org-export-show-temporary-export-buffer'
 is non-nil."
   (interactive)
-  (let ((outbuf
-	 (org-export-to-buffer
-	  'e-html "*Org E-HTML Export*"
-	  subtreep visible-only body-only ext-plist)))
-    ;; Set major mode.
-    (with-current-buffer outbuf (nxml-mode))
-    (when org-export-show-temporary-export-buffer
-      (switch-to-buffer-other-window outbuf))))
+  (if async
+      (org-export-async-start
+	  (lambda (output)
+	    (with-current-buffer (get-buffer-create "*Org E-HTML Export*")
+	      (erase-buffer)
+	      (insert output)
+	      (goto-char (point-min))
+	      (nxml-mode)
+	      (when org-export-show-temporary-export-buffer
+		(org-export-add-to-stack (current-buffer) 'e-html))))
+	`(org-export-as 'e-html ,subtreep ,visible-only ,body-only ',ext-plist))
+    (let ((outbuf (org-export-to-buffer
+		   'e-html "*Org E-HTML Export*"
+		   subtreep visible-only body-only ext-plist)))
+      ;; Set major mode.
+      (with-current-buffer outbuf (nxml-mode))
+      (when org-export-show-temporary-export-buffer
+	(switch-to-buffer-other-window outbuf)))))
 
 ;;;###autoload
 (defun org-e-html-export-to-html
-  (&optional subtreep visible-only body-only ext-plist)
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to a HTML file.
 
 If narrowing is active in the current buffer, only export its
@@ -2791,6 +2807,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting file should be accessible through
+the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -2810,8 +2830,16 @@ Return output file's name."
   (let* ((extension (concat "." org-e-html-extension))
 	 (file (org-export-output-file-name extension subtreep))
 	 (org-export-coding-system org-e-html-coding-system))
-    (org-export-to-file
-     'e-html file subtreep visible-only body-only ext-plist)))
+    (if async
+	(org-export-async-start
+	    (lambda (f) (org-export-add-to-stack f 'e-latex))
+	  (let ((org-export-coding-system org-e-html-coding-system))
+	    `(expand-file-name
+	      (org-export-to-file
+	       'e-html ,file ,subtreep ,visible-only ,body-only ',ext-plist))))
+      (let ((org-export-coding-system org-e-html-coding-system))
+	(org-export-to-file
+	 'e-html file subtreep visible-only body-only ext-plist)))))
 
 ;;;###autoload
 (defun org-e-html-publish-to-html (plist filename pub-dir)

+ 71 - 26
contrib/lisp/org-e-icalendar.el

@@ -274,12 +274,11 @@ re-read the iCalendar file.")
   ((:filter-headline . org-e-icalendar-clear-blank-lines))
   :menu-entry
   (?c "Export to iCalendar"
-      ((?f "Current file"
-	   (lambda (s v b) (org-e-icalendar-export-to-ics s v b)))
+      ((?f "Current file" org-e-icalendar-export-to-ics)
        (?a "All agenda files"
-	   (lambda (s v b) (org-e-icalendar-export-agenda-files)))
+	   (lambda (a s v b) (org-e-icalendar-export-agenda-files a)))
        (?c "Combine all agenda files"
-	   (lambda (s v b) (org-e-icalendar-combine-agenda-files))))))
+	   (lambda (a s v b) (org-e-icalendar-combine-agenda-files a))))))
 
 
 
@@ -789,7 +788,8 @@ CALSCALE:GREGORIAN\n"
 ;;; Interactive Functions
 
 ;;;###autoload
-(defun org-e-icalendar-export-to-ics (&optional subtreep visible-only body-only)
+(defun org-e-icalendar-export-to-ics
+  (&optional async subtreep visible-only body-only)
   "Export current buffer to an iCalendar file.
 
 If narrowing is active in the current buffer, only export its
@@ -797,6 +797,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting file should be accessible through
+the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -814,35 +818,76 @@ Return ICS file name."
       (org-e-icalendar-create-uid file 'warn-user)))
   ;; Export part.  Since this back-end is backed up by `e-ascii',
   ;; ensure links will not be collected at the end of sections.
-  (let ((outfile (org-export-output-file-name ".ics" subtreep))
-	(org-e-ascii-links-to-notes nil))
-    (org-export-to-file 'e-icalendar outfile subtreep visible-only body-only
-			'(:ascii-charset utf-8))
-    (run-hook-with-args 'org-e-icalendar-after-save-hook outfile)
-    outfile))
+  (let ((outfile (org-export-output-file-name ".ics" subtreep)))
+    (if async
+	(org-export-async-start
+	    (lambda (f)
+	      (org-export-add-to-stack f 'e-icalendar)
+	      (run-hook-with-args 'org-e-icalendar-after-save-hook f))
+	  `(let ((org-e-ascii-links-to-notes nil))
+	     (expand-file-name
+	      (org-export-to-file
+	       'e-icalendar ,outfile ,subtreep ,visible-only ,body-only
+	       '(:ascii-charset utf-8)))))
+      (let ((org-e-ascii-links-to-notes nil))
+	(org-export-to-file 'e-icalendar outfile subtreep visible-only body-only
+			    '(:ascii-charset utf-8)))
+      (run-hook-with-args 'org-e-icalendar-after-save-hook outfile)
+      outfile)))
 
 ;;;###autoload
-(defun org-e-icalendar-export-agenda-files ()
-  "Export all agenda files to iCalendar files."
+(defun org-e-icalendar-export-agenda-files (&optional async)
+  "Export all agenda files to iCalendar files.
+When optional argument ASYNC is non-nil, export happens in an
+external process."
   (interactive)
-  (let ((files (org-agenda-files t)))
-    (org-agenda-prepare-buffers files)
-    (unwind-protect
-	(mapc (lambda (file)
-		(catch 'nextfile
-		  (org-check-agenda-file file)
-		  (with-current-buffer (org-get-agenda-file-buffer file)
-		    (org-e-icalendar-export-to-ics))))
-	      files)
-      (org-release-buffers org-agenda-new-buffers))))
+  (if async
+      ;; Asynchronous export is not interactive, so we will not call
+      ;; `org-check-agenda-file'.  Instead we remove any non-existent
+      ;; agenda file from the list.
+      (let ((files (org-remove-if-not 'file-exists-p (org-agenda-files t))))
+	(org-export-async-start
+	    (lambda (results)
+	      (mapc (lambda (f) (org-export-add-to-stack f 'icalendar))
+		    results))
+	  `(let (output-files)
+	     (mapc (lambda (file)
+		     (with-current-buffer (org-get-agenda-file-buffer file)
+		       (push (expand-file-name (org-e-icalendar-export-to-ics))
+			     output-files)))
+		   ',files)
+	     output-files)))
+    (let ((files (org-agenda-files t)))
+      (org-agenda-prepare-buffers files)
+      (unwind-protect
+	  (mapc (lambda (file)
+		  (catch 'nextfile
+		    (org-check-agenda-file file)
+		    (with-current-buffer (org-get-agenda-file-buffer file)
+		      (org-e-icalendar-export-to-ics))))
+		files)
+	(org-release-buffers org-agenda-new-buffers)))))
 
 ;;;###autoload
-(defun org-e-icalendar-combine-agenda-files ()
+(defun org-e-icalendar-combine-agenda-files (&optional async)
   "Combine all agenda files into a single iCalendar file.
-The file is stored under the name
+
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting file should be accessible through
+the `org-export-stack' interface.
+
+The file is stored under the name chosen in
 `org-e-icalendar-combined-agenda-file'."
   (interactive)
-  (apply 'org-e-icalendar--combine-files nil (org-agenda-files t)))
+  (if async
+      (let ((files (org-remove-if-not 'file-exists-p (org-agenda-files t))))
+	(org-export-async-start
+	    (lambda (dummy)
+	      (org-export-add-to-stack
+	       (expand-file-name org-e-icalendar-combined-agenda-file)
+	       'e-icalendar))
+	  `(apply 'org-e-icalendar--combine-files nil ',files)))
+    (apply 'org-e-icalendar--combine-files nil (org-agenda-files t))))
 
 (defun org-e-icalendar-export-current-agenda ()
   "Export current agenda view to an iCalendar file.

+ 55 - 14
contrib/lisp/org-e-latex.el

@@ -156,7 +156,9 @@
        (?l "As TEX file" org-e-latex-export-to-latex)
        (?p "As PDF file" org-e-latex-export-to-pdf)
        (?o "As PDF file and open"
-	   (lambda (s v b) (org-open-file (org-e-latex-export-to-pdf s v b))))))
+	   (lambda (a s v b)
+	     (if a (org-e-latex-export-to-pdf t s v b)
+	       (org-open-file (org-e-latex-export-to-pdf nil s v b)))))))
   :options-alist ((:date "DATE" nil org-e-latex-date-format t)
 		  (:latex-class "LATEX_CLASS" nil org-e-latex-default-class t)
 		  (:latex-class-options "LATEX_CLASS_OPTIONS" nil nil t)
@@ -2639,7 +2641,7 @@ contextual information."
 
 ;;;###autoload
 (defun org-e-latex-export-as-latex
-  (&optional subtreep visible-only body-only ext-plist)
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer as a LaTeX buffer.
 
 If narrowing is active in the current buffer, only export its
@@ -2647,6 +2649,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting buffer should be accessible
+through the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -2665,16 +2671,27 @@ Export is done in a buffer named \"*Org E-LATEX Export*\", which
 will be displayed when `org-export-show-temporary-export-buffer'
 is non-nil."
   (interactive)
-  (let ((outbuf (org-export-to-buffer
-		 'e-latex "*Org E-LATEX Export*"
-		 subtreep visible-only body-only ext-plist)))
-    (with-current-buffer outbuf (LaTeX-mode))
-    (when org-export-show-temporary-export-buffer
-      (switch-to-buffer-other-window outbuf))))
+  (if async
+      (org-export-async-start
+	  (lambda (output)
+	    (with-current-buffer (get-buffer-create "*Org E-LATEX Export*")
+	      (erase-buffer)
+	      (insert output)
+	      (goto-char (point-min))
+	      (LaTeX-mode)
+	      (org-export-add-to-stack (current-buffer) 'e-latex)))
+	`(org-export-as 'e-latex ,subtreep ,visible-only ,body-only
+			',ext-plist))
+    (let ((outbuf
+	   (org-export-to-buffer 'e-latex "*Org E-LATEX Export*"
+				 subtreep visible-only body-only ext-plist)))
+      (with-current-buffer outbuf (LaTeX-mode))
+      (when org-export-show-temporary-export-buffer
+	(switch-to-buffer-other-window outbuf)))))
 
 ;;;###autoload
 (defun org-e-latex-export-to-latex
-  (&optional subtreep visible-only body-only ext-plist)
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to a LaTeX file.
 
 If narrowing is active in the current buffer, only export its
@@ -2682,6 +2699,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting file should be accessible through
+the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -2699,12 +2720,18 @@ file-local settings.
 Return output file's name."
   (interactive)
   (let ((outfile (org-export-output-file-name ".tex" subtreep)))
-    (org-export-to-file
-     'e-latex outfile subtreep visible-only body-only ext-plist)))
+    (if async
+	(org-export-async-start
+	    (lambda (f) (org-export-add-to-stack f 'e-latex))
+	  `(expand-file-name
+	    (org-export-to-file
+	     'e-latex ,outfile ,subtreep ,visible-only ,body-only ',ext-plist)))
+      (org-export-to-file
+       'e-latex outfile subtreep visible-only body-only ext-plist))))
 
 ;;;###autoload
 (defun org-e-latex-export-to-pdf
-  (&optional subtreep visible-only body-only ext-plist)
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to LaTeX then process through to PDF.
 
 If narrowing is active in the current buffer, only export its
@@ -2712,6 +2739,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting file should be accessible through
+the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -2728,8 +2759,18 @@ file-local settings.
 
 Return PDF file's name."
   (interactive)
-  (org-e-latex-compile
-   (org-e-latex-export-to-latex subtreep visible-only body-only ext-plist)))
+  (if async
+      (let ((outfile (org-export-output-file-name ".tex" subtreep)))
+	(org-export-async-start
+	    (lambda (f) (org-export-add-to-stack f 'e-latex))
+	  `(expand-file-name
+	    (org-e-latex-compile
+	     (org-export-to-file
+	      'e-latex ,outfile ,subtreep ,visible-only ,body-only
+	      ',ext-plist)))))
+    (org-e-latex-compile
+     (org-e-latex-export-to-latex
+      nil subtreep visible-only body-only ext-plist))))
 
 (defun org-e-latex-compile (texfile)
   "Compile a TeX file.

+ 32 - 7
contrib/lisp/org-e-man.el

@@ -108,7 +108,9 @@
       ((?m "As MAN file" org-e-man-export-to-man)
        (?p "As PDF file" org-e-man-export-to-pdf)
        (?o "As PDF file and open"
-	   (lambda (s v b) (org-open-file (org-e-man-export-to-pdf s v b))))))
+	   (lambda (a s v b)
+	     (if a (org-e-man-export-to-pdf t s v b)
+	       (org-open-file (org-e-man-export-to-pdf nil s v b)))))))
   :options-alist
   ((:man-class "MAN_CLASS" nil nil t)
    (:man-class-options "MAN_CLASS_OPTIONS" nil nil t)
@@ -1146,7 +1148,7 @@ contextual information."
 ;;; Interactive functions
 
 (defun org-e-man-export-to-man
-  (&optional subtreep visible-only body-only ext-plist)
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to a Man file.
 
 If narrowing is active in the current buffer, only export its
@@ -1154,6 +1156,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting file should be accessible through
+the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -1171,11 +1177,17 @@ file-local settings.
 Return output file's name."
   (interactive)
   (let ((outfile (org-export-output-file-name ".man" subtreep)))
-    (org-export-to-file
-     'e-man outfile subtreep visible-only body-only ext-plist)))
+    (if async
+	(org-export-async-start
+	    (lambda (f) (org-export-add-to-stack f 'e-man))
+	  `(expand-file-name
+	    (org-export-to-file
+	     'e-man ,outfile ,subtreep ,visible-only ,body-only ',ext-plist)))
+      (org-export-to-file
+       'e-man outfile subtreep visible-only body-only ext-plist))))
 
 (defun org-e-man-export-to-pdf
-  (&optional subtreep visible-only body-only ext-plist)
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to Groff then process through to PDF.
 
 If narrowing is active in the current buffer, only export its
@@ -1183,6 +1195,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting file should be accessible through
+the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -1199,8 +1215,17 @@ file-local settings.
 
 Return PDF file's name."
   (interactive)
-  (org-e-man-compile
-   (org-e-man-export-to-man subtreep visible-only body-only ext-plist)))
+  (if async
+      (let ((outfile (org-export-output-file-name ".man" subtreep)))
+	(org-export-async-start
+	    (lambda (f) (org-export-add-to-stack f 'e-man))
+	  `(expand-file-name
+	    (org-e-man-compile
+	     (org-export-to-file
+	      'e-man ,outfile ,subtreep ,visible-only ,body-only
+	      ',ext-plist)))))
+    (org-e-man-compile
+     (org-e-man-export-to-man nil subtreep visible-only body-only ext-plist))))
 
 (defun org-e-man-compile (file)
   "Compile a Groff file.

+ 48 - 23
contrib/lisp/org-e-odt.el

@@ -91,8 +91,9 @@
   (?o "Export to ODT"
       ((?o "As ODT file" org-e-odt-export-to-odt)
        (?O "As ODT file and open"
-	   (lambda (s v b)
-	     (org-open-file (org-e-odt-export-to-odt s v b) 'system)))))
+	   (lambda (a s v b)
+	     (if a (org-e-odt-export-to-odt t s v)
+	       (org-open-file (org-e-odt-export-to-odt nil s v) 'system))))))
   :options-alist
   ((:odt-styles-file "ODT_STYLES_FILE" nil nil t)
    (:LaTeX-fragments nil "LaTeX" org-export-with-LaTeX-fragments)))
@@ -3828,8 +3829,7 @@ formula file."
 ;;;; Export to OpenDocument Text
 
 ;;;###autoload
-(defun org-e-odt-export-to-odt
-  (&optional subtreep visible-only body-only ext-plist)
+(defun org-e-odt-export-to-odt (&optional async subtreep visible-only ext-plist)
   "Export current buffer to a HTML file.
 
 If narrowing is active in the current buffer, only export its
@@ -3837,6 +3837,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting file should be accessible through
+the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -3844,31 +3848,52 @@ first.
 When optional argument VISIBLE-ONLY is non-nil, don't export
 contents of hidden elements.
 
-When optional argument BODY-ONLY is non-nil, only write code
-between \"\\begin{document}\" and \"\\end{document}\".
-
 EXT-PLIST, when provided, is a property list with external
 parameters overriding Org default settings, but still inferior to
 file-local settings.
 
 Return output file's name."
   (interactive)
-  (org-e-odt--export-wrap
-   (org-export-output-file-name ".odt" subtreep)
-   (let* ((org-e-odt-embedded-images-count 0)
-	  (org-e-odt-embedded-formulas-count 0)
-	  (org-e-odt-automatic-styles nil)
-	  (org-e-odt-object-counters nil)
-	  ;; Let `htmlfontify' know that we are interested in collecting
-	  ;; styles.
-	  (hfy-user-sheet-assoc nil))
-     ;; Initialize content.xml and kick-off the export process.
-     (let ((out-buf (progn
-		      (require 'nxml-mode)
-		      (let ((nxml-auto-insert-xml-declaration-flag nil))
-			(find-file-noselect
-			 (concat org-e-odt-zip-dir "content.xml") t)))))
-       (org-export-to-buffer 'e-odt out-buf subtreep visible-only body-only)))))
+  (let ((outfile (org-export-output-file-name ".odt" subtreep)))
+    (if async
+	(org-export-async-start (lambda (f) (org-export-add-to-stack f 'e-odt))
+	  `(expand-file-name
+	    (org-e-odt--export-wrap
+	     ,outfile
+	     (let* ((org-e-odt-embedded-images-count 0)
+		    (org-e-odt-embedded-formulas-count 0)
+		    (org-e-odt-automatic-styles nil)
+		    (org-e-odt-object-counters nil)
+		    ;; Let `htmlfontify' know that we are interested in
+		    ;; collecting styles.
+		    (hfy-user-sheet-assoc nil))
+	       ;; Initialize content.xml and kick-off the export
+	       ;; process.
+	       (let ((out-buf
+		      (progn
+			(require 'nxml-mode)
+			(let ((nxml-auto-insert-xml-declaration-flag nil))
+			  (find-file-noselect
+			   (concat org-e-odt-zip-dir "content.xml") t)))))
+		 (org-export-to-buffer
+		  'e-odt out-buf ,subtreep ,visible-only nil ',ext-plist))))))
+      (org-e-odt--export-wrap
+       outfile
+       (let* ((org-e-odt-embedded-images-count 0)
+	      (org-e-odt-embedded-formulas-count 0)
+	      (org-e-odt-automatic-styles nil)
+	      (org-e-odt-object-counters nil)
+	      ;; Let `htmlfontify' know that we are interested in collecting
+	      ;; styles.
+	      (hfy-user-sheet-assoc nil))
+	 ;; Initialize content.xml and kick-off the export process.
+	 (let ((out-buf (progn
+			  (require 'nxml-mode)
+			  (let ((nxml-auto-insert-xml-declaration-flag nil))
+			    (find-file-noselect
+			     (concat org-e-odt-zip-dir "content.xml") t)))))
+	   (org-export-to-buffer
+	    'e-odt out-buf subtreep visible-only nil ext-plist)))))))
 
 
 ;;;; Convert between OpenDocument and other formats

+ 55 - 35
contrib/lisp/org-e-publish.el

@@ -42,13 +42,9 @@
 (require 'format-spec)
 (require 'org-export)
 
-(declare-function org-e-latex-compile "org-e-latex" (texfile))
-
 
 
 ;;; Variables
-(defvar org-e-publish-initial-buffer nil
-  "The buffer `org-e-publish' has been called from.")
 
 (defvar org-e-publish-temp-files nil
   "Temporary list of files to be published.")
@@ -817,8 +813,15 @@ It returns time in `current-time' format."
 (defalias 'org-e-publish-project 'org-e-publish)
 
 ;;;###autoload
-(defun org-e-publish (project &optional force)
-  "Publish PROJECT."
+(defun org-e-publish (project &optional force async)
+  "Publish PROJECT.
+
+PROJECT is either a project name, as a string, or a project
+alist (see `org-e-publish-project-alist' variable).
+
+When optional argument FORCE is non-nil, force publishing all
+files in PROJECT.  With a non-nil optional argument ASYNC,
+publishing will be done asynchronously, in another process."
   (interactive
    (list
     (assoc (org-icompleting-read
@@ -826,52 +829,69 @@ It returns time in `current-time' format."
 	    org-e-publish-project-alist nil t)
 	   org-e-publish-project-alist)
     current-prefix-arg))
-  (setq org-e-publish-initial-buffer (current-buffer))
-  (save-window-excursion
-    (let* ((org-e-publish-use-timestamps-flag
-	    (if force nil org-e-publish-use-timestamps-flag)))
-      (org-e-publish-projects
-       (if (stringp project)
-	   ;; If this function is called in batch mode, project is
-	   ;; still a string here.
-	   (list (assoc project org-e-publish-project-alist))
-	 (list project))))))
+  (let ((project-alist  (if (not (stringp project)) (list project)
+			  ;; If this function is called in batch mode,
+			  ;; project is still a string here.
+			  (list (assoc project org-e-publish-project-alist)))))
+    (if async
+	(org-export-async-start 'ignore
+	  `(let ((org-e-publish-use-timestamps-flag
+		  (if ',force nil ,org-e-publish-use-timestamps-flag)))
+	     (org-e-publish-projects ',project-alist)))
+      (save-window-excursion
+	(let* ((org-e-publish-use-timestamps-flag
+		(if force nil org-e-publish-use-timestamps-flag)))
+	  (org-e-publish-projects project-alist))))))
 
 ;;;###autoload
-(defun org-e-publish-all (&optional force)
+(defun org-e-publish-all (&optional force async)
   "Publish all projects.
-With prefix argument, remove all files in the timestamp
-directory and force publishing all files."
+With prefix argument FORCE, remove all files in the timestamp
+directory and force publishing all projects.  With a non-nil
+optional argument ASYNC, publishing will be done asynchronously,
+in another process."
   (interactive "P")
-  (when force (org-e-publish-remove-all-timestamps))
-  (save-window-excursion
-    (let ((org-e-publish-use-timestamps-flag
-	   (if force nil org-e-publish-use-timestamps-flag)))
-      (org-e-publish-projects org-e-publish-project-alist))))
+  (if async
+      (org-export-async-start 'ignore
+	`(when ',force (org-e-publish-remove-all-timestamps))
+	`(let ((org-e-publish-use-timestamps-flag
+		(if ',force nil ,org-e-publish-use-timestamps-flag)))
+	   (org-e-publish-projects ',org-e-publish-project-alist)))
+    (when force (org-e-publish-remove-all-timestamps))
+    (save-window-excursion
+      (let ((org-e-publish-use-timestamps-flag
+	     (if force nil org-e-publish-use-timestamps-flag)))
+	(org-e-publish-projects org-e-publish-project-alist)))))
 
 
 ;;;###autoload
-(defun org-e-publish-current-file (&optional force)
+(defun org-e-publish-current-file (&optional force async)
   "Publish the current file.
-With prefix argument, force publish the file."
+With prefix argument FORCE, force publish the file.  When
+optional argument ASYNC is non-nil, publishing will be done
+asynchronously, in another process."
   (interactive "P")
-  (save-window-excursion
-    (let ((org-e-publish-use-timestamps-flag
-	   (if force nil org-e-publish-use-timestamps-flag)))
-      (org-e-publish-file (buffer-file-name (buffer-base-buffer))))))
+  (let ((file (buffer-file-name (buffer-base-buffer))))
+    (if async
+	(org-export-async-start 'ignore
+	  `(let ((org-e-publish-use-timestamps-flag
+		  (if ',force nil ,org-e-publish-use-timestamps-flag)))
+	     (org-e-publish-file ,file)))
+      (save-window-excursion
+	(let ((org-e-publish-use-timestamps-flag
+	       (if force nil org-e-publish-use-timestamps-flag)))
+	  (org-e-publish-file file))))))
 
 ;;;###autoload
-(defun org-e-publish-current-project (&optional force)
+(defun org-e-publish-current-project (&optional force async)
   "Publish the project associated with the current file.
 With a prefix argument, force publishing of all files in
 the project."
   (interactive "P")
   (save-window-excursion
     (let ((project (org-e-publish-get-project-from-filename
-		    (buffer-file-name (buffer-base-buffer)) 'up))
-	  (org-e-publish-use-timestamps-flag
-	   (if force nil org-e-publish-use-timestamps-flag)))
-      (if project (org-e-publish project)
+		    (buffer-file-name (buffer-base-buffer)) 'up)))
+      (if project (org-e-publish project force async)
 	(error "File %s is not part of any known project"
 	       (buffer-file-name (buffer-base-buffer)))))))
 

+ 31 - 6
contrib/lisp/org-e-texinfo.el

@@ -1657,7 +1657,7 @@ contextual information."
 ;;; Interactive functions
 
 (defun org-e-texinfo-export-to-texinfo
-  (&optional subtreep visible-only body-only ext-plist)
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to a Texinfo file.
 
 If narrowing is active in the current buffer, only export its
@@ -1665,6 +1665,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting file should be accessible through
+the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -1682,11 +1686,18 @@ file-local settings.
 Return output file's name."
   (interactive)
   (let ((outfile (org-export-output-file-name ".texi" subtreep)))
-    (org-export-to-file
-     'e-texinfo outfile subtreep visible-only body-only ext-plist)))
+    (if async
+	(org-export-async-start
+	    (lambda (f) (org-export-add-to-stack f 'e-texinfo))
+	  `(expand-file-name
+	    (org-export-to-file
+	     'e-texinfo ,outfile ,subtreep ,visible-only ,body-only
+	     ',ext-plist)))
+      (org-export-to-file
+       'e-texinfo outfile subtreep visible-only body-only ext-plist))))
 
 (defun org-e-texinfo-export-to-info
-  (&optional subtreep visible-only body-only ext-plist)
+  (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to Texinfo then process through to INFO.
 
 If narrowing is active in the current buffer, only export its
@@ -1694,6 +1705,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting file should be accessible through
+the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -1713,8 +1728,18 @@ directory.
 
 Return INFO file's name."
   (interactive)
-  (org-e-texinfo-compile
-   (org-e-texinfo-export-to-texinfo subtreep visible-only body-only ext-plist)))
+  (if async
+      (let ((outfile (org-export-output-file-name ".texi" subtreep)))
+	(org-export-async-start
+	    (lambda (f) (org-export-add-to-stack f 'e-texinfo))
+	  `(expand-file-name
+	    (org-e-texinfo-compile
+	     (org-export-to-file
+	      'e-texinfo ,outfile ,subtreep ,visible-only ,body-only
+	      ',ext-plist)))))
+    (org-e-texinfo-compile
+     (org-e-texinfo-export-to-texinfo
+      nil subtreep visible-only body-only ext-plist))))
 
 (defun org-e-texinfo-compile (file)
   "Compile a texinfo file.

+ 451 - 79
contrib/lisp/org-export.el

@@ -65,8 +65,14 @@
 ;; customizable should belong to the `org-export-BACKEND' group.
 ;;
 ;; Tools for common tasks across back-ends are implemented in the
-;; penultimate part of this file.  A dispatcher for standard back-ends
-;; is provided in the last one.
+;; following part of then file.
+;;
+;; Then, a wrapper macro for asynchronous export,
+;; `org-export-async-start', along with tools to display results. are
+;; given in the penultimate part.
+;;
+;; Eventually, a dispatcher (`org-export-dispatch') for standard
+;; back-ends is provided in the last one.
 
 ;;; Code:
 
@@ -74,11 +80,12 @@
 (require 'org-element)
 (require 'ob-exp)
 
-(declare-function org-e-publish "org-e-publish" (project &optional force))
-(declare-function org-e-publish-all "org-e-publish" (&optional force))
-(declare-function org-e-publish-current-file "org-e-publish" (&optional force))
+(declare-function org-e-publish "org-e-publish" (project &optional force async))
+(declare-function org-e-publish-all "org-e-publish" (&optional force async))
+(declare-function
+ org-e-publish-current-file "org-e-publish" (&optional force async))
 (declare-function org-e-publish-current-project "org-e-publish"
-		  (&optional force))
+		  (&optional force async))
 
 (defvar org-e-publish-project-alist)
 (defvar org-table-number-fraction)
@@ -251,6 +258,25 @@ whose extension is either \"png\", \"jpeg\", \"jpg\", \"gif\",
 See `org-export-inline-image-p' for more information about
 rules.")
 
+(defvar org-export-async-debug nil
+  "Non-nil means asynchronous export process should leave data behind.
+
+This data is found in the appropriate \"*Org Export Process*\"
+buffer, and in files prefixed with \"org-export-process\" and
+located in `temporary-file-directory'.
+
+When non-nil, it will also set `debug-on-error' to a non-nil
+value in the external process.")
+
+(defvar org-export-stack-contents nil
+  "Record asynchronously generated export results and processes.
+This is an alist: its CAR is the source of the
+result (destination file or buffer for a finished process,
+original buffer for a running one) and its CDR is a list
+containing the back-end used, as a symbol, and either a process
+or the time at which it finished.  It is used to build the menu
+from `org-export-stack'.")
+
 (defvar org-export-registered-backends nil
   "List of backends currently available in the exporter.
 
@@ -703,6 +729,21 @@ these cases."
   :group 'org-export-general
   :type 'boolean)
 
+(defcustom org-export-in-background nil
+  "Non-nil means export and publishing commands will run in background.
+Results from an asynchronous export are never displayed.  You can
+retrieve them with \\[org-export-stack]."
+  :group 'org-export-general
+  :type 'boolean)
+
+(defcustom org-export-async-init-file user-init-file
+  "File used to initialize external export process.
+Value must be an absolute file name.  It defaults to user's
+initialization file.  Though, a specific configuration makes the
+process faster and the export more portable."
+  :group 'org-export-general
+  :type '(file :must-match t))
+
 (defcustom org-export-dispatch-use-expert-ui nil
   "Non-nil means using a non-intrusive `org-export-dispatch'.
 In that case, no help buffer is displayed.  Though, an indicator
@@ -811,9 +852,10 @@ keywords are understood:
 
       ACTION-OR-MENU is either a function or an alist.
 
-      If it is an action, it will be called with three arguments:
-      SUBTREEP, VISIBLE-ONLY and BODY-ONLY.  See `org-export-as'
-      for further explanations.
+      If it is an action, it will be called with four
+      arguments (booleans): ASYNC, SUBTREEP, VISIBLE-ONLY and
+      BODY-ONLY.  See `org-export-as' for further explanations on
+      some of them.
 
       If it is an alist, associations should follow the
       pattern:
@@ -1910,15 +1952,13 @@ Return transcoded string."
 	      (cond
 	       ;; Ignored element/object.
 	       ((memq data (plist-get info :ignore-list)) nil)
-	       ;; Plain text.  All residual text properties from parse
-	       ;; tree (i.e. `:parent' property) are removed.
+	       ;; Plain text.
 	       ((eq type 'plain-text)
-		(org-no-properties
-		 (org-export-filter-apply-functions
-		  (plist-get info :filter-plain-text)
-		  (let ((transcoder (org-export-transcoder data info)))
-		    (if transcoder (funcall transcoder data info) data))
-		  info)))
+		(org-export-filter-apply-functions
+		 (plist-get info :filter-plain-text)
+		 (let ((transcoder (org-export-transcoder data info)))
+		   (if transcoder (funcall transcoder data info) data))
+		 info))
 	       ;; Uninterpreted element/object: change it back to Org
 	       ;; syntax and export again resulting raw string.
 	       ((not (org-export--interpret-p data info))
@@ -2533,7 +2573,7 @@ Return the updated communication channel."
 ;; but a copy of it (with the same buffer-local variables and
 ;; visibility), where macros and include keywords are expanded and
 ;; Babel blocks are executed, if appropriate.
-;; `org-export-with-current-buffer-copy' macro prepares that copy.
+;; `org-export-with-buffer-copy' macro prepares that copy.
 ;;
 ;; File inclusion is taken care of by
 ;; `org-export-expand-include-keyword' and
@@ -2588,7 +2628,7 @@ Return code as a string."
       ;; Initialize communication channel with original buffer
       ;; attributes, unavailable in its copy.
       (let ((info (org-export--get-buffer-attributes)) tree)
-	(org-export-with-current-buffer-copy
+	(org-export-with-buffer-copy
 	 ;; Run first hook with current back-end as argument.
 	 (run-hook-with-args 'org-export-before-processing-hook backend)
 	 ;; Update communication channel and get parse tree.  Buffer
@@ -2645,11 +2685,14 @@ Return code as a string."
 		      (or (org-export-data tree info) "")))
 	       (template (cdr (assq 'template
 				    (plist-get info :translate-alist))))
-	       (output (org-export-filter-apply-functions
-			(plist-get info :filter-final-output)
-			(if (or (not (functionp template)) body-only) body
-			  (funcall template body info))
-			info)))
+	       ;; Remove all text properties since they cannot be
+	       ;; retrieved from an external process.
+	       (output (org-no-properties
+			(org-export-filter-apply-functions
+			 (plist-get info :filter-final-output)
+			 (if (or (not (functionp template)) body-only) body
+			   (funcall template body info))
+			 info))))
 	  ;; Maybe add final OUTPUT to kill ring, then return it.
 	  (when (and org-export-copy-to-kill-ring (org-string-nw-p output))
 	    (org-kill-new output))
@@ -2752,32 +2795,94 @@ determined."
      ((file-name-absolute-p base-name) (concat base-name extension))
      (t (concat (file-name-as-directory ".") base-name extension)))))
 
-(defmacro org-export-with-current-buffer-copy (&rest body)
+(defun org-export-copy-buffer ()
+  "Return a copy of the current buffer.
+The copy preserves Org buffer-local variables, visibility and
+narrowing."
+  (let ((copy-buffer-fun (org-export--generate-copy-script (current-buffer)))
+	(new-buf (generate-new-buffer (buffer-name))))
+    (with-current-buffer new-buf
+      (funcall copy-buffer-fun)
+      (set-buffer-modified-p nil))
+    new-buf))
+
+(defmacro org-export-with-buffer-copy (&rest body)
   "Apply BODY in a copy of the current buffer.
-
-The copy preserves local variables and visibility of the original
-buffer.
-
-Point is at buffer's beginning when BODY is applied."
-  (declare (debug (body)))
-  (org-with-gensyms (original-buffer offset buffer-string overlays region)
-    `(let* ((,original-buffer (current-buffer))
-	    (,region (list (point-min) (point-max)))
-	    (,buffer-string (org-with-wide-buffer (buffer-string)))
-	    (,overlays (mapcar 'copy-overlay (apply 'overlays-in ,region))))
-       (with-temp-buffer
-	 (let ((buffer-invisibility-spec nil))
-	   (org-clone-local-variables
-	    ,original-buffer
-	    "^\\(org-\\|orgtbl-\\|major-mode$\\|outline-\\(regexp\\|level\\)$\\)")
-	   (insert ,buffer-string)
-	   (apply 'narrow-to-region ,region)
-	   (mapc (lambda (ov)
-		   (move-overlay
-		    ov (overlay-start ov) (overlay-end ov) (current-buffer)))
-		 ,overlays)
-	   (goto-char (point-min))
-	   (progn ,@body))))))
+The copy preserves local variables, visibility and contents of
+the original buffer.  Point is at the beginning of the buffer
+when BODY is applied."
+  (declare (debug t))
+  (org-with-gensyms (buf-copy)
+    `(let ((,buf-copy (org-export-copy-buffer)))
+       (unwind-protect
+	   (with-current-buffer ,buf-copy
+	     (goto-char (point-min))
+	     (progn ,@body))
+	 (and (buffer-live-p ,buf-copy)
+	      ;; Kill copy without confirmation.
+	      (progn (with-current-buffer ,buf-copy
+		       (restore-buffer-modified-p nil))
+		     (kill-buffer ,buf-copy)))))))
+
+(defun org-export--generate-copy-script (buffer)
+  "Generate a function duplicating BUFFER.
+
+The copy will preserve local variables, visibility, contents and
+narrowing of the original buffer.  If a region was active in
+BUFFER, contents will be narrowed to that region instead.
+
+The resulting function can be eval'ed at a later time, from
+another buffer, effectively cloning the original buffer there."
+  (with-current-buffer buffer
+    `(lambda ()
+       (let ((inhibit-modification-hooks t))
+	 ;; Buffer local variables.
+	 ,@(let (local-vars)
+	     (mapc
+	      (lambda (entry)
+		(when (consp entry)
+		  (let ((var (car entry))
+			(val (cdr entry)))
+		    (and (not (eq var 'org-font-lock-keywords))
+			 (or (memq var
+				   '(major-mode default-directory
+						buffer-file-name outline-level
+						outline-regexp
+						buffer-invisibility-spec))
+			     (string-match "^\\(org-\\|orgtbl-\\)"
+					   (symbol-name var)))
+			 ;; Skip unreadable values, as they cannot be
+			 ;; sent to external process.
+			 (or (not val) (ignore-errors (read (format "%S" val))))
+			 (push `(set (make-local-variable (quote ,var))
+				     (quote ,val))
+			       local-vars)))))
+	      (buffer-local-variables (buffer-base-buffer)))
+	     local-vars)
+	 ;; Whole buffer contents.
+	 (insert
+	  ,(org-with-wide-buffer
+	    (buffer-substring-no-properties
+	     (point-min) (point-max))))
+	 ;; Narrowing.
+	 ,(if (org-region-active-p)
+	      `(narrow-to-region ,(region-beginning) ,(region-end))
+	    `(narrow-to-region ,(point-min) ,(point-max)))
+	 ;; Current position of point.
+	 (goto-char ,(point))
+	 ;; Overlays with invisible property.
+	 ,@(let (ov-set)
+	     (mapc
+	      (lambda (ov)
+		(let ((invis-prop (overlay-get ov 'invisible)))
+		  (when invis-prop
+		    (push `(overlay-put
+			    (make-overlay ,(overlay-start ov)
+					  ,(overlay-end ov))
+			    'invisible (quote ,invis-prop))
+			  ov-set))))
+	      (overlays-in (point-min) (point-max)))
+	     ov-set)))))
 
 (defun org-export-expand-include-keyword (&optional included dir)
   "Expand every include keyword in buffer.
@@ -2935,7 +3040,7 @@ This function will return an error if the current buffer is
 visiting a file."
   ;; Get a pristine copy of current buffer so Babel references can be
   ;; properly resolved.
-  (let* (clone-buffer-hook (reference (clone-buffer)))
+  (let ((reference (org-export-copy-buffer)))
     (unwind-protect (let ((org-current-export-file reference))
 		      (org-export-blocks-preprocess))
       (kill-buffer reference))))
@@ -4854,6 +4959,253 @@ to `:default' encoding. If it fails, return S."
 	s)))
 
 
+
+;;; 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.
+;;
+;; 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-delete', `org-export--stack-view' and
+;;`org-export--stack-clear'.
+;;
+;; For back-ends, `org-export-add-to-stack' add a new source to stack.
+;; It should used whenever `org-export-async-start' is called.
+
+(defmacro org-export-async-start  (fun &rest body)
+  "Call function FUN on the results returned by BODY evaluation.
+
+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.  Examples for, respectively a temporary buffer and
+a file are:
+
+  \(org-export-async-start
+      \(lambda (output)
+        \(with-current-buffer (get-buffer-create \"*Org BACKEND Export*\")
+        \(erase-buffer)
+        \(insert output)
+        \(goto-char (point-min))
+        \(org-export-add-to-stack (current-buffer) 'backend)))
+    `(org-export-as 'backend ,subtreep ,visible-only ,body-only ',ext-plist))
+
+and
+
+  \(org-export-async-start
+      \(lambda (f) (org-export-add-to-stack f 'backend))
+    `(expand-file-name
+      \(org-export-to-file
+       'backend ,outfile ,subtreep ,visible-only ,body-only ',ext-plist)))"
+  (declare (indent 1) (debug t))
+  (org-with-gensyms (process temp-file copy-fun proc-buffer handler)
+    ;; 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-export--generate-copy-script (current-buffer)))
+	     (,temp-file (make-temp-file "org-export-process")))
+	 (with-temp-file ,temp-file
+	   (insert
+	    (format
+	     "%S"
+	     `(with-temp-buffer
+		,(when org-export-async-debug '(setq debug-on-error t))
+		;; Initialize `org-mode' in the external process.
+		(org-mode)
+		;; Re-create current buffer there.
+		(funcall ,,copy-fun)
+		(restore-buffer-modified-p nil)
+		;; Sexp to evaluate in the buffer.
+		(print (progn ,,@body))))))
+	 ;; Start external process.
+	 (let* ((process-connection-type nil)
+		(,proc-buffer (generate-new-buffer-name "*Org Export Process*"))
+		(,process
+		 (start-process
+		  "org-export-process" ,proc-buffer
+		  (expand-file-name invocation-name invocation-directory)
+		  "-Q" "--batch"
+		  "-l" org-export-async-init-file
+		  "-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.
+	   (set-process-sentinel
+	    ,process
+	    (let ((handler #',fun))
+	      `(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)))))))))))))
+
+(defun org-export-add-to-stack (source backend &optional process)
+  "Add a new result to export stack if not present already.
+
+SOURCE is a buffer or a file name containing export results.
+BACKEND is a symbol representing export back-end used to generate
+it.
+
+Entries already pointing to SOURCE and unavailable entries are
+removed beforehand.  Return the new stack."
+  (setq org-export-stack-contents
+	(cons (list source backend (or process (current-time)))
+	      (org-export--stack-remove source))))
+
+(defun org-export-stack ()
+  "Menu for asynchronous export results and running processes."
+  (interactive)
+  (let ((buffer (get-buffer-create "*Org Export Stack*")))
+    (set-buffer buffer)
+    (when (zerop (buffer-size)) (org-export-stack-mode))
+    (org-export--stack-refresh)
+    (pop-to-buffer buffer))
+  (message "Type \"q\" to quit, \"?\" for help"))
+
+(defun org-export--stack-source-at-point ()
+  "Return source from export results at point in stack."
+  (let ((source (car (nth (1- (org-current-line)) org-export-stack-contents))))
+    (if (not source) (error "Source unavailable, please refresh buffer")
+      (let ((source-name (if (stringp source) source (buffer-name source))))
+	(if (save-excursion
+	      (beginning-of-line)
+	      (looking-at (concat ".* +" (regexp-quote source-name) "$")))
+	    source
+	  ;; SOURCE is not consistent with current line.  The stack
+	  ;; view is outdated.
+	  (error "Source unavailable; type `g' to update buffer"))))))
+
+(defun org-export--stack-clear ()
+  "Remove all entries from export stack."
+  (interactive)
+  (setq org-export-stack-contents nil))
+
+(defun org-export--stack-refresh (&rest dummy)
+  "Refresh the asynchronous export stack.
+DUMMY is ignored.  Unavailable sources are removed from the list.
+Return the new stack."
+  (let ((inhibit-read-only t))
+    (org-preserve-lc
+     (erase-buffer)
+     (insert (concat
+	      (let ((counter 0))
+		(mapconcat
+		 (lambda (entry)
+		   (let ((proc-p (processp (nth 2 entry))))
+		     (concat
+		      ;; Back-end.
+		      (format " %-12s  " (or (nth 1 entry) ""))
+		      ;; Age.
+		      (let ((data (nth 2 entry)))
+			(if proc-p (format " %6s  " (process-status data))
+			  ;; Compute age of the results.
+			  (org-format-seconds
+			   "%4h:%.2m  "
+			   (float-time (time-since data)))))
+		      ;; Source.
+		      (format " %s"
+			      (let ((source (car entry)))
+				(if (stringp source) source
+				  (buffer-name source)))))))
+		 ;; Clear stack from exited processes, dead buffers or
+		 ;; non-existent files.
+		 (setq org-export-stack-contents
+		       (org-remove-if-not
+			(lambda (el)
+			  (if (processp (nth 2 el))
+			      (buffer-live-p (process-buffer (nth 2 el)))
+			    (let ((source (car el)))
+			      (if (bufferp source) (buffer-live-p source)
+				(file-exists-p source)))))
+			org-export-stack-contents)) "\n")))))))
+
+(defun org-export--stack-remove (&optional source)
+  "Remove export results at point from stack.
+If optional argument SOURCE is non-nil, remove it instead."
+  (interactive)
+  (let ((source (or source (org-export--stack-source-at-point))))
+    (setq org-export-stack-contents
+	  (org-remove-if (lambda (el) (equal (car el) source))
+			 org-export-stack-contents))))
+
+(defun org-export--stack-view ()
+  "View export results at point in stack."
+  (interactive)
+  (let ((source (org-export--stack-source-at-point)))
+    (cond ((processp source)
+	   (org-switch-to-buffer-other-window (process-buffer source)))
+	  ((bufferp source) (org-switch-to-buffer-other-window source))
+	  (t (org-open-file source)))))
+
+(defconst org-export-stack-mode-map
+  (let ((km (make-sparse-keymap)))
+    (define-key km " " 'next-line)
+    (define-key km "n" 'next-line)
+    (define-key km "\C-n" 'next-line)
+    (define-key km [down] 'next-line)
+    (define-key km "p" 'previous-line)
+    (define-key km "\C-p" 'previous-line)
+    (define-key km "\C-?" 'previous-line)
+    (define-key km [up] 'previous-line)
+    (define-key km "C" 'org-export--stack-clear)
+    (define-key km "v" 'org-export--stack-view)
+    (define-key km (kbd "RET") 'org-export--stack-view)
+    (define-key km "d" 'org-export--stack-remove)
+    km)
+  "Keymap for Org Export Stack.")
+
+(define-derived-mode org-export-stack-mode special-mode "Org-Stack"
+  "Mode for displaying asynchronous export stack.
+
+Type \\[org-export-stack] to visualize the asynchronous export
+stack.
+
+In an Org Export Stack buffer, use \\[org-export--stack-view] to view export output
+on current line, \\[org-export--stack-remove] to remove it from the stack and \\[org-export--stack-clear] to clear 
+stack completely.
+
+Removal entries in an Org Export Stack buffer doesn't affect
+files or buffers, only view in the stack.
+
+\\{org-export-stack-mode-map}"
+  (abbrev-mode 0)
+  (auto-fill-mode 0)
+  (setq buffer-read-only t
+	buffer-undo-list t
+	truncate-lines t
+	header-line-format
+	'(:eval
+	  (format "  %-12s | %6s | %s" "Back-End" "Age" "Source")))
+  (add-hook 'post-command-hook 'org-export--stack-refresh nil t)
+  (set (make-local-variable 'revert-buffer-function)
+       'org-export--stack-refresh))
+
+
 
 ;;; The Dispatcher
 ;;
@@ -4874,38 +5226,49 @@ to switch to one or the other.
 
 When called with C-u prefix ARG, repeat the last export action,
 with the same set of options used back then, on the current
-buffer."
+buffer.
+
+When called with a double universal argument, display the
+asynchronous export stack directly."
   (interactive "P")
-  (let* ((input (or (and arg org-export-dispatch-last-action)
-		    (save-window-excursion
-		      (unwind-protect
-			  ;; Store this export command.
-			  (setq org-export-dispatch-last-action
-				(org-export-dispatch-ui
-				 (list org-export-initial-scope)
-				 nil
-				 org-export-dispatch-use-expert-ui))
-			(and (get-buffer "*Org Export Dispatcher*")
-			     (kill-buffer "*Org Export Dispatcher*"))))))
+  (let* ((input
+	  (cond ((equal arg '(16)) '(stack))
+		((and arg org-export-dispatch-last-action))
+		(t (save-window-excursion
+		     (unwind-protect
+			 ;; Store this export command.
+			 (setq org-export-dispatch-last-action
+			       (org-export-dispatch-ui
+				(list org-export-initial-scope
+				      (and org-export-in-background 'async))
+				nil
+				org-export-dispatch-use-expert-ui))
+		       (and (get-buffer "*Org Export Dispatcher*")
+			    (kill-buffer "*Org Export Dispatcher*")))))))
 	 (action (car input))
 	 (optns (cdr input)))
     (case action
       ;; First handle special hard-coded actions.
-      (publish-current-file (org-e-publish-current-file (memq 'force optns)))
+      (stack (org-export-stack))
+      (publish-current-file
+       (org-e-publish-current-file (memq 'force optns) (memq 'async optns)))
       (publish-current-project
-       (org-e-publish-current-project (memq 'force optns)))
+       (org-e-publish-current-project (memq 'force optns) (memq 'async optns)))
       (publish-choose-project
        (org-e-publish (assoc (org-icompleting-read
 			      "Publish project: "
 			      org-e-publish-project-alist nil t)
 			     org-e-publish-project-alist)
-		      (memq 'force optns)))
-      (publish-all (org-e-publish-all (memq 'force optns)))
-      (otherwise
-       (funcall action
-		(memq 'subtree optns)
-		(memq 'visible optns)
-		(memq 'body optns))))))
+		      (memq 'force optns)
+		      (memq 'async optns)))
+      (publish-all (org-e-publish-all (memq 'force optns) (memq 'async optns)))
+      (otherwise (funcall action
+			  ;; Return a symbol instead of a list to ease
+			  ;; asynchronous export macro use.
+			  (and (memq 'async optns) t)
+			  (and (memq 'subtree optns) t)
+			  (and (memq 'visible optns) t)
+			  (and (memq 'body optns) t))))))
 
 (defun org-export-dispatch-ui (options first-key expertp)
   "Handle interface for `org-export-dispatch'.
@@ -4916,6 +5279,7 @@ export.  It can contain any of the following symbols:
 `subtree' restricts export to current subtree
 `visible' restricts export to visible part of buffer.
 `force'   force publishing files.
+`async'   use asynchronous export process
 
 FIRST-KEY is the key pressed to select the first level menu.  It
 is nil when this menu hasn't been selected yet.
@@ -4951,10 +5315,10 @@ back to standard interface."
 			       ((numberp key-b) t)))))
 		    (lambda (a b) (< (car a) (car b)))))
 	 ;; Compute a list of allowed keys based on the first key
-	 ;; pressed, if any.  Some keys (?1, ?2, ?3, ?4 and ?q) are
-	 ;; always available.
+	 ;; pressed, if any.  Some keys (?1, ?2, ?3, ?4, ?5 and ?q)
+	 ;; are always available.
 	 (allowed-keys
-	  (nconc (list ?1 ?2 ?3 ?4)
+	  (nconc (list ?1 ?2 ?3 ?4 ?5)
 		 (if (not first-key) (org-uniquify (mapcar 'car backends))
 		   (let (sub-menu)
 		     (dolist (backend backends (sort (mapcar 'car sub-menu) '<))
@@ -4962,6 +5326,7 @@ back to standard interface."
 			 (setq sub-menu (append (nth 2 backend) sub-menu))))))
 		 (cond ((eq first-key ?P) (list ?f ?p ?x ?a))
 		       ((not first-key) (list ?P)))
+		 (list ?&)
 		 (when expertp (list ??))
 		 (list ?q)))
 	 ;; Build the help menu for standard UI.
@@ -4971,7 +5336,8 @@ back to standard interface."
 	     ;; Options are hard-coded.
 	     (format "Options
     [%s] Body only:    %s       [%s] Visible only:     %s
-    [%s] Export scope: %s   [%s] Force publishing: %s\n"
+    [%s] Export scope: %s   [%s] Force publishing: %s
+    [%s] Asynchronous export: %s\n"
 		     (funcall fontify-key "1" t)
 		     (if (memq 'body options) "On " "Off")
 		     (funcall fontify-key "2" t)
@@ -4979,7 +5345,9 @@ back to standard interface."
 		     (funcall fontify-key "3" t)
 		     (if (memq 'subtree options) "Subtree" "Buffer ")
 		     (funcall fontify-key "4" t)
-		     (if (memq 'force options) "On " "Off"))
+		     (if (memq 'force options) "On " "Off")
+		     (funcall fontify-key "5" t)
+		     (if (memq 'async options) "On " "Off"))
 	     ;; Display registered back-end entries.  When a key
 	     ;; appears for the second time, do not create another
 	     ;; entry, but append its sub-menu to existing menu.
@@ -5020,6 +5388,7 @@ back to standard interface."
 		     (funcall fontify-key "p" ?P)
 		     (funcall fontify-key "x" ?P)
 		     (funcall fontify-key "a" ?P))
+	     (format "\[%s] Export stack\n" (funcall fontify-key "&" t))
 	     (format "\[%s] %s"
 		     (funcall fontify-key "q" t)
 		     (if first-key "Main menu" "Exit")))))
@@ -5028,11 +5397,12 @@ back to standard interface."
 	 (expert-prompt
 	  (when expertp
 	    (format
-	     "Export command (Options: %s%s%s%s) [%s]: "
+	     "Export command (Options: %s%s%s%s%s) [%s]: "
 	     (if (memq 'body options) (funcall fontify-key "b" t) "-")
 	     (if (memq 'visible options) (funcall fontify-key "v" t) "-")
 	     (if (memq 'subtree options) (funcall fontify-key "s" t) "-")
 	     (if (memq 'force options) (funcall fontify-key "f" t) "-")
+	     (if (memq 'async options) (funcall fontify-key "a" t) "-")
 	     (concat allowed-keys)))))
     ;; With expert UI, just read key with a fancy prompt.  In standard
     ;; UI, display an intrusive help buffer.
@@ -5085,11 +5455,13 @@ options as CDR."
      ;; Help key: Switch back to standard interface if
      ;; expert UI was active.
      ((eq key ??) (org-export-dispatch-ui options first-key nil))
+     ;; Switch to asynchronous export stack.
+     ((eq key ?&) '(stack))
      ;; Toggle export options.
-     ((memq key '(?1 ?2 ?3 ?4))
+     ((memq key '(?1 ?2 ?3 ?4 ?5))
       (org-export-dispatch-ui
        (let ((option (case key (?1 'body) (?2 'visible) (?3 'subtree)
-			   (?4 'force))))
+			   (?4 'force) (?5 'async))))
 	 (if (memq option options) (remq option options)
 	   (cons option options)))
        first-key expertp))

+ 36 - 11
contrib/lisp/org-md.el

@@ -59,10 +59,12 @@ This variable can be set to either `atx' or `setext'."
   :menu-entry
   (?m "Export to Markdown"
       ((?M "To temporary buffer"
-	   (lambda (s v b) (org-md-export-as-markdown s v)))
-       (?m "To file" (lambda (s v b) (org-md-export-to-markdown s v)))
+	   (lambda (a s v b) (org-md-export-as-markdown a s v)))
+       (?m "To file" (lambda (a s v b) (org-md-export-to-markdown a s v)))
        (?o "To file and open"
-	   (lambda (s v b) (org-open-file (org-md-export-to-markdown s v))))))
+	   (lambda (a s v b)
+	     (if a (org-md-export-to-markdown t s v)
+	       (org-open-file (org-md-export-to-markdown nil s v)))))))
   :translate-alist ((bold . org-md-bold)
 		    (code . org-md-verbatim)
 		    (example-block . org-md-example-block)
@@ -411,7 +413,7 @@ as a communication channel."
 ;;; Interactive function
 
 ;;;###autoload
-(defun org-md-export-as-markdown (&optional subtreep visible-only)
+(defun org-md-export-as-markdown (&optional async subtreep visible-only)
   "Export current buffer to a text buffer.
 
 If narrowing is active in the current buffer, only export its
@@ -419,6 +421,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting buffer should be accessible
+through the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -430,15 +436,25 @@ Export is done in a buffer named \"*Org MD Export*\", which will
 be displayed when `org-export-show-temporary-export-buffer' is
 non-nil."
   (interactive)
-  (let ((outbuf (org-export-to-buffer
-		 'md "*Org MD Export*" subtreep visible-only)))
-    (with-current-buffer outbuf (text-mode))
-    (when org-export-show-temporary-export-buffer
-      (switch-to-buffer-other-window outbuf))))
+  (if async
+      (org-export-async-start
+	  (lambda (output)
+	    (with-current-buffer (get-buffer-create "*Org MD Export*")
+	      (erase-buffer)
+	      (insert output)
+	      (goto-char (point-min))
+	      (text-mode)
+	      (org-export-add-to-stack (current-buffer) 'md)))
+	`(org-export-as 'md ,subtreep ,visible-only))
+    (let ((outbuf (org-export-to-buffer
+		   'md "*Org MD Export*" subtreep visible-only)))
+      (with-current-buffer outbuf (text-mode))
+      (when org-export-show-temporary-export-buffer
+	(switch-to-buffer-other-window outbuf)))))
 
 
 ;;;###autoload
-(defun org-md-export-to-markdown (&optional subtreep visible-only)
+(defun org-md-export-to-markdown (&optional async subtreep visible-only)
   "Export current buffer to a Markdown file.
 
 If narrowing is active in the current buffer, only export its
@@ -446,6 +462,10 @@ narrowed part.
 
 If a region is active, export that region.
 
+A non-nil optional argument ASYNC means the process should happen
+asynchronously.  The resulting file should be accessible through
+the `org-export-stack' interface.
+
 When optional argument SUBTREEP is non-nil, export the sub-tree
 at point, extracting information from the headline properties
 first.
@@ -456,7 +476,12 @@ contents of hidden elements.
 Return output file's name."
   (interactive)
   (let ((outfile (org-export-output-file-name ".md" subtreep)))
-    (org-export-to-file 'md outfile subtreep visible-only)))
+    (if async
+	(org-export-async-start
+	    (lambda (f) (org-export-add-to-stack f 'md))
+	  `(expand-file-name
+	    (org-export-to-file 'md ,outfile ,subtreep ,visible-only)))
+      (org-export-to-file 'md outfile subtreep visible-only))))
 
 
 (provide 'org-md)