Browse Source

org-export-as: Do not update buffer settings when not modified

* lisp/ox.el (org-export-as): Use `buffer-chars-modified-tick' and
avoid extra invocations of `org-set-regexps-and-options' and
`org-update-radio-target-regexp' when the buffer is not changed.
Also, disable folding checks.  Folding is irrelevant inside export
buffer.
Ihor Radchenko 2 years ago
parent
commit
076dd92acc
1 changed files with 135 additions and 128 deletions
  1. 135 128
      lisp/ox.el

+ 135 - 128
lisp/ox.el

@@ -2938,135 +2938,142 @@ still inferior to file-local settings.
 Return code as a string."
   (when (symbolp backend) (setq backend (org-export-get-backend backend)))
   (org-export-barf-if-invalid-backend backend)
-  (save-excursion
-    (save-restriction
-      ;; Narrow buffer to an appropriate region or subtree for
-      ;; parsing.  If parsing subtree, be sure to remove main
-      ;; headline, planning data and property drawer.
-      (cond ((org-region-active-p)
-	     (narrow-to-region (region-beginning) (region-end)))
-	    (subtreep
-	     (org-narrow-to-subtree)
-	     (goto-char (point-min))
-	     (org-end-of-meta-data)
-	     (narrow-to-region (point) (point-max))))
-      ;; Initialize communication channel with original buffer
-      ;; attributes, unavailable in its copy.
-      (let* ((org-export-current-backend (org-export-backend-name backend))
-	     (info (org-combine-plists
-		    (org-export--get-export-attributes
-		     backend subtreep visible-only body-only)
-		    (org-export--get-buffer-attributes)))
-	     (parsed-keywords
-	      (delq nil
-		    (mapcar (lambda (o) (and (eq (nth 4 o) 'parse) (nth 1 o)))
-			    (append (org-export-get-all-options backend)
-				    org-export-options-alist))))
-	     tree)
-	;; Update communication channel and get parse tree.  Buffer
-	;; isn't parsed directly.  Instead, all buffer modifications
-	;; and consequent parsing are undertaken in a temporary copy.
-	(org-export-with-buffer-copy
-	 ;; Run first hook with current back-end's name as argument.
-	 (run-hook-with-args 'org-export-before-processing-hook
-			     (org-export-backend-name backend))
-	 (org-export-expand-include-keyword)
-	 (org-export--delete-comment-trees)
-	 (org-macro-initialize-templates org-export-global-macros)
-	 (org-macro-replace-all org-macro-templates parsed-keywords)
-	 ;; Refresh buffer properties and radio targets after previous
-	 ;; potentially invasive changes.
-	 (org-set-regexps-and-options)
-	 (org-update-radio-target-regexp)
-	 ;;  Possibly execute Babel code.  Re-run a macro expansion
-	 ;;  specifically for {{{results}}} since inline source blocks
-	 ;;  may have generated some more.  Refresh buffer properties
-	 ;;  and radio targets another time.
-	 (when org-export-use-babel
-	   (org-babel-exp-process-buffer)
-	   (org-macro-replace-all '(("results" . "$1")) parsed-keywords)
+  (org-fold-core-ignore-modifications
+    (save-excursion
+      (save-restriction
+        ;; Narrow buffer to an appropriate region or subtree for
+        ;; parsing.  If parsing subtree, be sure to remove main
+        ;; headline, planning data and property drawer.
+        (cond ((org-region-active-p)
+	       (narrow-to-region (region-beginning) (region-end)))
+	      (subtreep
+	       (org-narrow-to-subtree)
+	       (goto-char (point-min))
+	       (org-end-of-meta-data)
+	       (narrow-to-region (point) (point-max))))
+        ;; Initialize communication channel with original buffer
+        ;; attributes, unavailable in its copy.
+        (let* ((org-export-current-backend (org-export-backend-name backend))
+	       (info (org-combine-plists
+		      (org-export--get-export-attributes
+		       backend subtreep visible-only body-only)
+		      (org-export--get-buffer-attributes)))
+	       (parsed-keywords
+	        (delq nil
+		      (mapcar (lambda (o) (and (eq (nth 4 o) 'parse) (nth 1 o)))
+			      (append (org-export-get-all-options backend)
+				      org-export-options-alist))))
+	       tree modified-tick)
+	  ;; Update communication channel and get parse tree.  Buffer
+	  ;; isn't parsed directly.  Instead, all buffer modifications
+	  ;; and consequent parsing are undertaken in a temporary copy.
+	  (org-export-with-buffer-copy
+           (font-lock-mode -1)
+	   ;; Run first hook with current back-end's name as argument.
+	   (run-hook-with-args 'org-export-before-processing-hook
+			       (org-export-backend-name backend))
+	   (org-export-expand-include-keyword)
+	   (org-export--delete-comment-trees)
+	   (org-macro-initialize-templates org-export-global-macros)
+	   (org-macro-replace-all org-macro-templates parsed-keywords)
+	   ;; Refresh buffer properties and radio targets after previous
+	   ;; potentially invasive changes.
 	   (org-set-regexps-and-options)
-	   (org-update-radio-target-regexp))
-	 ;; Run last hook with current back-end's name as argument.
-	 ;; Update buffer properties and radio targets one last time
-	 ;; before parsing.
-	 (goto-char (point-min))
-	 (save-excursion
-	   (run-hook-with-args 'org-export-before-parsing-hook
-			       (org-export-backend-name backend)))
-	 (org-set-regexps-and-options)
-	 (org-update-radio-target-regexp)
-	 ;; Update communication channel with environment.
-	 (setq info
-	       (org-combine-plists
-		info (org-export-get-environment backend subtreep ext-plist)))
-         ;; Pre-process citations environment, i.e. install
-	 ;; bibliography list, and citation processor in INFO.
-	 (org-cite-store-bibliography info)
-         (org-cite-store-export-processor info)
-	 ;; De-activate uninterpreted data from parsed keywords.
-	 (dolist (entry (append (org-export-get-all-options backend)
-				org-export-options-alist))
-	   (pcase entry
-	     (`(,p ,_ ,_ ,_ parse)
-	      (let ((value (plist-get info p)))
-		(plist-put info
-			   p
-			   (org-export--remove-uninterpreted-data value info))))
-	     (_ nil)))
-	 ;; Install user's and developer's filters.
-	 (setq info (org-export-install-filters info))
-	 ;; Call options filters and update export options.  We do not
-	 ;; use `org-export-filter-apply-functions' here since the
-	 ;; arity of such filters is different.
-	 (let ((backend-name (org-export-backend-name backend)))
-	   (dolist (filter (plist-get info :filter-options))
-	     (let ((result (funcall filter info backend-name)))
-	       (when result (setq info result)))))
-	 ;; Parse buffer.
-	 (setq tree (org-element-parse-buffer nil visible-only))
-	 ;; Prune tree from non-exported elements and transform
-	 ;; uninterpreted elements or objects in both parse tree and
-	 ;; communication channel.
-	 (org-export--prune-tree tree info)
-	 (org-export--remove-uninterpreted-data tree info)
-	 ;; Call parse tree filters.
-	 (setq tree
-	       (org-export-filter-apply-functions
-		(plist-get info :filter-parse-tree) tree info))
-	 ;; Now tree is complete, compute its properties and add them
-	 ;; to communication channel.
-	 (setq info (org-export--collect-tree-properties tree info))
-         ;; Process citations and bibliography.  Replace each citation
-	 ;; and "print_bibliography" keyword in the parse tree with
-	 ;; the output of the selected citation export processor.
-         (org-cite-process-citations info)
-         (org-cite-process-bibliography info)
-	 ;; Eventually transcode TREE.  Wrap the resulting string into
-	 ;; a template.
-	 (let* ((body (org-element-normalize-string
-		       (or (org-export-data tree info) "")))
-		(inner-template (cdr (assq 'inner-template
-					   (plist-get info :translate-alist))))
-		(full-body (org-export-filter-apply-functions
-			    (plist-get info :filter-body)
-			    (if (not (functionp inner-template)) body
-			      (funcall inner-template body info))
-			    info))
-		(template (cdr (assq 'template
-				     (plist-get info :translate-alist))))
-                (output
-                 (if (or (not (functionp template)) body-only) full-body
-	           (funcall template full-body info))))
-           ;; Call citation export finalizer.
-           (setq output (org-cite-finalize-export output info))
-	   ;; Remove all text properties since they cannot be
-	   ;; retrieved from an external process.  Finally call
-	   ;; final-output filter and return result.
-	   (org-no-properties
-	    (org-export-filter-apply-functions
-	     (plist-get info :filter-final-output)
-	     output info))))))))
+	   (org-update-radio-target-regexp)
+           (setq modified-tick (buffer-chars-modified-tick))
+	   ;;  Possibly execute Babel code.  Re-run a macro expansion
+	   ;;  specifically for {{{results}}} since inline source blocks
+	   ;;  may have generated some more.  Refresh buffer properties
+	   ;;  and radio targets another time.
+	   (when org-export-use-babel
+	     (org-babel-exp-process-buffer)
+	     (org-macro-replace-all '(("results" . "$1")) parsed-keywords)
+             (unless (eq modified-tick (buffer-chars-modified-tick))
+	       (org-set-regexps-and-options)
+	       (org-update-radio-target-regexp))
+             (setq modified-tick (buffer-chars-modified-tick)))
+	   ;; Run last hook with current back-end's name as argument.
+	   ;; Update buffer properties and radio targets one last time
+	   ;; before parsing.
+	   (goto-char (point-min))
+	   (save-excursion
+	     (run-hook-with-args 'org-export-before-parsing-hook
+			         (org-export-backend-name backend)))
+           (unless (eq modified-tick (buffer-chars-modified-tick))
+	     (org-set-regexps-and-options)
+	     (org-update-radio-target-regexp))
+           (setq modified-tick (buffer-chars-modified-tick))
+	   ;; Update communication channel with environment.
+	   (setq info
+	         (org-combine-plists
+		  info (org-export-get-environment backend subtreep ext-plist)))
+           ;; Pre-process citations environment, i.e. install
+	   ;; bibliography list, and citation processor in INFO.
+	   (org-cite-store-bibliography info)
+           (org-cite-store-export-processor info)
+	   ;; De-activate uninterpreted data from parsed keywords.
+	   (dolist (entry (append (org-export-get-all-options backend)
+				  org-export-options-alist))
+	     (pcase entry
+	       (`(,p ,_ ,_ ,_ parse)
+	        (let ((value (plist-get info p)))
+		  (plist-put info
+			     p
+			     (org-export--remove-uninterpreted-data value info))))
+	       (_ nil)))
+	   ;; Install user's and developer's filters.
+	   (setq info (org-export-install-filters info))
+	   ;; Call options filters and update export options.  We do not
+	   ;; use `org-export-filter-apply-functions' here since the
+	   ;; arity of such filters is different.
+	   (let ((backend-name (org-export-backend-name backend)))
+	     (dolist (filter (plist-get info :filter-options))
+	       (let ((result (funcall filter info backend-name)))
+	         (when result (setq info result)))))
+	   ;; Parse buffer.
+	   (setq tree (org-element-parse-buffer nil visible-only))
+	   ;; Prune tree from non-exported elements and transform
+	   ;; uninterpreted elements or objects in both parse tree and
+	   ;; communication channel.
+	   (org-export--prune-tree tree info)
+	   (org-export--remove-uninterpreted-data tree info)
+	   ;; Call parse tree filters.
+	   (setq tree
+	         (org-export-filter-apply-functions
+		  (plist-get info :filter-parse-tree) tree info))
+	   ;; Now tree is complete, compute its properties and add them
+	   ;; to communication channel.
+	   (setq info (org-export--collect-tree-properties tree info))
+           ;; Process citations and bibliography.  Replace each citation
+	   ;; and "print_bibliography" keyword in the parse tree with
+	   ;; the output of the selected citation export processor.
+           (org-cite-process-citations info)
+           (org-cite-process-bibliography info)
+	   ;; Eventually transcode TREE.  Wrap the resulting string into
+	   ;; a template.
+	   (let* ((body (org-element-normalize-string
+		         (or (org-export-data tree info) "")))
+		  (inner-template (cdr (assq 'inner-template
+					     (plist-get info :translate-alist))))
+		  (full-body (org-export-filter-apply-functions
+			      (plist-get info :filter-body)
+			      (if (not (functionp inner-template)) body
+			        (funcall inner-template body info))
+			      info))
+		  (template (cdr (assq 'template
+				       (plist-get info :translate-alist))))
+                  (output
+                   (if (or (not (functionp template)) body-only) full-body
+	             (funcall template full-body info))))
+             ;; Call citation export finalizer.
+             (setq output (org-cite-finalize-export output info))
+	     ;; Remove all text properties since they cannot be
+	     ;; retrieved from an external process.  Finally call
+	     ;; final-output filter and return result.
+	     (org-no-properties
+	      (org-export-filter-apply-functions
+	       (plist-get info :filter-final-output)
+	       output info)))))))))
 
 ;;;###autoload
 (defun org-export-string-as (string backend &optional body-only ext-plist)