From 176b959c4f55fc7b3f59a0022284d6826d14725d Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Sat, 4 Feb 2012 21:49:58 +0100 Subject: [PATCH] Handling of file inclusion through keywords is done before export * contrib/lisp/org-element.el (org-element-map): Remove included file expansion part. * contrib/lisp/org-export.el (org-export-as): Expand include keywords before executing blocks. (org-export-expand-include-keyword, org-export-prepare-file-contents): New functions. (org-export-included-file, org-export-parse-included-file): Removed functions. * EXPERIMENTAL/org-e-ascii.el (org-e-ascii-keyword): Remove include keyword handling. * EXPERIMENTAL/org-e-latex.el (org-e-latex-keyword): Remove include keyword handling. Back-ends do not need anymore to take care of #+include keywords. This change is required since file inclusion can potentially break any structure. Hence, it should be done before parsing. --- EXPERIMENTAL/org-e-ascii.el | 4 +- EXPERIMENTAL/org-e-latex.el | 4 +- contrib/lisp/org-element.el | 35 ----- contrib/lisp/org-export.el | 285 +++++++++++++++++++++--------------- 4 files changed, 170 insertions(+), 158 deletions(-) diff --git a/EXPERIMENTAL/org-e-ascii.el b/EXPERIMENTAL/org-e-ascii.el index a2862f065..e1b8a671a 100644 --- a/EXPERIMENTAL/org-e-ascii.el +++ b/EXPERIMENTAL/org-e-ascii.el @@ -1328,9 +1328,7 @@ information." ((string= "tables" value) (org-e-ascii--list-tables keyword info)) ((string= "listings" value) - (org-e-ascii--list-listings keyword info))))) - ((string= key "include") - (org-export-included-file keyword 'e-ascii info))))) + (org-e-ascii--list-listings keyword info)))))))) ;;;; Latex Environment diff --git a/EXPERIMENTAL/org-e-latex.el b/EXPERIMENTAL/org-e-latex.el index 88849a61a..3f94ca39d 100644 --- a/EXPERIMENTAL/org-e-latex.el +++ b/EXPERIMENTAL/org-e-latex.el @@ -1257,9 +1257,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." "\\tableofcontents"))) ((string= "tables" value) "\\listoftables") ((string= "figures" value) "\\listoffigures") - ((string= "listings" value) "\\listoflistings")))) - ((string= key "include") - (org-export-included-file keyword 'e-latex info))))) + ((string= "listings" value) "\\listoflistings"))))))) ;;;; Latex Environment diff --git a/contrib/lisp/org-element.el b/contrib/lisp/org-element.el index 9f9f9da5e..a8b014d4b 100644 --- a/contrib/lisp/org-element.el +++ b/contrib/lisp/org-element.el @@ -3011,41 +3011,6 @@ Nil values returned from FUN are ignored in the result." (eq (plist-get info :with-archived-trees) 'headline) (org-element-get-property :archivedp --blob)) (funcall accumulate-maybe --type types fun --blob --local)) - ;; At an include keyword: apply mapping to its - ;; contents. - ((and --local - (eq --type 'keyword) - (string= - (downcase (org-element-get-property :key --blob)) - "include")) - (funcall accumulate-maybe --type types fun --blob --local) - (let* ((--data - (org-export-parse-included-file --blob --local)) - (--value (org-element-get-property :value --blob)) - (--file - (and (string-match "^\"\\(\\S-+\\)\"" --value) - (match-string 1 --value)))) - (funcall - walk-tree --data - (org-combine-plists - --local - ;; Store full path of already included files - ;; to avoid recursive file inclusion. - `(:included-files - ,(cons (expand-file-name --file) - (plist-get --local :included-files)) - ;; Ensure that a top-level headline in the - ;; included file becomes a direct child of - ;; the current headline in the buffer. - :headline-offset - ,(- (let ((parent - (org-export-get-parent-headline - --blob --local))) - (if (not parent) 0 - (org-export-get-relative-level - parent --local))) - (1- (org-export-get-min-level - --data --local)))))))) ;; Limiting recursion to greater elements, and --BLOB ;; isn't one. ((and (eq --category 'greater-elements) diff --git a/contrib/lisp/org-export.el b/contrib/lisp/org-export.el index 85fb26861..d22d972ad 100644 --- a/contrib/lisp/org-export.el +++ b/contrib/lisp/org-export.el @@ -1876,9 +1876,19 @@ specified filters, if any, are called first." ;; Note that `org-export-as' doesn't really parse the current buffer, ;; but a copy of it (with the same buffer-local variables and -;; visibility), where Babel blocks are executed, if appropriate. +;; visibility), where include keywords are expanded and Babel blocks +;; are executed, if appropriate. ;; `org-export-with-current-buffer-copy' macro prepares that copy. +;; File inclusion is taken care of by +;; `org-export-expand-include-keyword' and +;; `org-export-prepare-file-contents'. Structure wise, including +;; a whole Org file in a buffer often makes little sense. For +;; example, if the file contains an headline and the include keyword +;; was within an item, the item should contain the headline. That's +;; why file inclusion should be done before any structure can be +;; associated to the file, that is before parsing. + (defun org-export-as (backend &optional subtreep visible-only body-only ext-plist) "Transcode current Org buffer into BACKEND code. @@ -1915,9 +1925,10 @@ Return code as a string." ;; Retrieve export options (INFO) and parsed tree (RAW-DATA), ;; Then options can be completed with tree properties. Note: ;; Buffer isn't parsed directly. Instead, a temporary copy is - ;; created, where all code blocks are evaluated. RAW-DATA is - ;; the parsed tree of the buffer resulting from that process. - ;; Eventually call `org-export-filter-parse-tree-functions'. + ;; created, where include keywords are expanded and code blocks + ;; are evaluated. RAW-DATA is the parsed tree of the buffer + ;; resulting from that process. Eventually call + ;; `org-export-filter-parse-tree-functions'. (let* ((info (org-export-collect-options backend subtreep ext-plist)) (raw-data (progn (when subtreep ; Only parse subtree contents. @@ -1927,6 +1938,7 @@ Return code as a string." (org-export-filter-apply-functions (plist-get info :filter-parse-tree) (org-export-with-current-buffer-copy + (org-export-expand-include-keyword nil) (let ((org-current-export-file (current-buffer))) (org-export-blocks-preprocess)) (org-element-parse-buffer nil visible-only)) @@ -2073,6 +2085,155 @@ Point is at buffer's beginning when BODY is applied." (progn ,@body)))))) (def-edebug-spec org-export-with-current-buffer-copy (body)) +(defun org-export-expand-include-keyword (included) + "Expand every include keyword in buffer. +INCLUDED is a list of included file names along with their line +restriction, when appropriate. It is used to avoid infinite +recursion." + (let ((case-fold-search nil)) + (goto-char (point-min)) + (while (re-search-forward "^[ \t]*#\\+include: \\(.*\\)" nil t) + (when (eq (car (save-match-data (org-element-at-point))) 'keyword) + (beginning-of-line) + ;; Extract arguments from keyword's value. + (let* ((value (match-string 1)) + (ind (org-get-indentation)) + (file (and (string-match "^\"\\(\\S-+\\)\"" value) + (prog1 (expand-file-name (match-string 1 value)) + (setq value (replace-match "" nil nil value))))) + (lines + (and (string-match + ":lines +\"\\(\\(?:[0-9]+\\)?-\\(?:[0-9]+\\)?\\)\"" value) + (prog1 (match-string 1 value) + (setq value (replace-match "" nil nil value))))) + (env (cond ((string-match "\\" value) 'example) + ((string-match "\\" value) "example") - ((string-match "\\