[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/org 5cde90e3c8 04/14: ox: Refactor org-export-expand-in
From: |
ELPA Syncer |
Subject: |
[elpa] externals/org 5cde90e3c8 04/14: ox: Refactor org-export-expand-include-keyword |
Date: |
Sun, 22 Jan 2023 10:58:10 -0500 (EST) |
branch: externals/org
commit 5cde90e3c8df5d95dd291025acf3bf3acdc248ac
Author: TEC <git@tecosaur.net>
Commit: Ihor Radchenko <yantar92@posteo.net>
ox: Refactor org-export-expand-include-keyword
* lisp/ox.el (org-export-expand-include-keyword): Split the parsing and
inclusion logic of the ~150 line `org-export-expand-include-keyword'
into two new functions: `org-export-parse-include-value' and
`org-export--blindly-expand-include'.
---
lisp/ox.el | 285 +++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 162 insertions(+), 123 deletions(-)
diff --git a/lisp/ox.el b/lisp/ox.el
index b9c57321f6..b6240cb1fc 100644
--- a/lisp/ox.el
+++ b/lisp/ox.el
@@ -3303,7 +3303,6 @@ not have `buffer-file-name' assigned."
(buffer-file-name (buffer-base-buffer))))
(case-fold-search t)
(file-prefix (make-hash-table :test #'equal))
- (current-prefix 0)
(footnotes (or footnotes (make-hash-table :test #'equal)))
(include-re "^[ \t]*#\\+INCLUDE:"))
;; If :minlevel is not set the text-property
@@ -3319,128 +3318,168 @@ not have `buffer-file-name' assigned."
(goto-char (point-min))
(while (re-search-forward include-re nil t)
(unless (org-in-commented-heading-p)
- (let ((element (save-match-data (org-element-at-point))))
- (when (eq (org-element-type element) 'keyword)
- (beginning-of-line)
- ;; Extract arguments from keyword's value.
- (let* ((value (org-element-property :value element))
- (ind (org-current-text-indentation))
- location
- (coding-system-for-read
- (or (and (string-match ":coding +\\(\\S-+\\)>" value)
- (prog1 (intern (match-string 1 value))
- (setq value (replace-match "" nil nil value))))
- coding-system-for-read))
- (file
- (and (string-match "^\\(\".+?\"\\|\\S-+\\)\\(?:\\s-+\\|$\\)"
- value)
- (prog1
- (save-match-data
- (let ((matched (match-string 1 value))
- stripped)
- (when (string-match "\\(::\\(.*?\\)\\)\"?\\'"
- matched)
- (setq location (match-string 2 matched))
- (setq matched
- (replace-match "" nil nil matched 1)))
- (setq stripped (org-strip-quotes matched))
- (if (org-url-p stripped)
- stripped
- (expand-file-name stripped dir))))
- (setq value (replace-match "" nil nil value)))))
- (only-contents
- (and (string-match ":only-contents *\\([^: \r\t\n]\\S-*\\)?"
- value)
- (prog1 (org-not-nil (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 "\\<example\\>" value) 'literal)
- ((string-match "\\<export\\(?: +\\(.*\\)\\)?" value)
- 'literal)
- ((string-match "\\<src\\(?: +\\(.*\\)\\)?" value)
- 'literal)))
- ;; Minimal level of included file defaults to the
- ;; child level of the current headline, if any, or
- ;; one. It only applies is the file is meant to be
- ;; included as an Org one.
- (minlevel
- (and (not env)
- (if (string-match ":minlevel +\\([0-9]+\\)" value)
- (prog1 (string-to-number (match-string 1 value))
- (setq value (replace-match "" nil nil value)))
- (get-text-property (point)
- :org-include-induced-level))))
- (args (and (eq env 'literal) (match-string 1 value)))
- (block (and (string-match "\\<\\(\\S-+\\)\\>" value)
- (match-string 1 value))))
- ;; Remove keyword.
- (delete-region (point) (line-beginning-position 2))
- (cond
- ((not file) nil)
- ((and (not (org-url-p file)) (not (file-readable-p file)))
- (error "Cannot include file %s" file))
- ;; Check if files has already been parsed. Look after
- ;; inclusion lines too, as different parts of the same
- ;; file can be included too.
- ((member (list file lines) included)
- (error "Recursive file inclusion: %s" file))
- (t
- (cond
- ((eq env 'literal)
- (insert
- (let ((ind-str (make-string ind ?\s))
- (arg-str (if (stringp args) (format " %s" args) ""))
- (contents
- (org-escape-code-in-string
- (org-export--prepare-file-contents file lines))))
- (format "%s#+BEGIN_%s%s\n%s%s#+END_%s\n"
- ind-str block arg-str contents ind-str block))))
- ((stringp block)
- (insert
- (let ((ind-str (make-string ind ?\s))
- (contents
- (org-export--prepare-file-contents file lines)))
- (format "%s#+BEGIN_%s\n%s%s#+END_%s\n"
- ind-str block contents ind-str block))))
- (t
- (insert
- (with-temp-buffer
- (let ((org-inhibit-startup t)
- (lines
- (if location
- (org-export--inclusion-absolute-lines
- file location only-contents lines)
- lines)))
- (org-mode)
- (insert
- (org-export--prepare-file-contents
- file lines ind minlevel
- (or (gethash file file-prefix)
- (puthash file
- (cl-incf current-prefix)
- file-prefix))
- footnotes
- includer-file)))
- (org-export-expand-include-keyword
- (cons (list file lines) included)
- (unless (org-url-p file)
- (file-name-directory file))
- footnotes includer-file)
- (buffer-string)))))
- ;; Expand footnotes after all files have been
- ;; included. Footnotes are stored at end of buffer.
- (unless included
- (org-with-wide-buffer
- (goto-char (point-max))
- (maphash (lambda (k v)
- (insert (format "\n[fn:%s] %s\n" k v)))
- footnotes))))))))))))
+ (let ((element (save-match-data (org-element-at-point))))
+ (when (eq (org-element-type element) 'keyword)
+ (beginning-of-line)
+ ;; Extract arguments from keyword's value.
+ (let* ((value (org-element-property :value element))
+ (parameters (org-export-parse-include-value value dir)))
+ ;; Remove keyword.
+ (delete-region (point) (line-beginning-position 2))
+ (pcase (plist-get parameters :file)
+ ((pred not) nil)
+ ((and (pred (not org-url-p)) (pred (not file-readable-p)) f)
+ (error "Cannot include file %s" f))
+ ;; Check if files has already been parsed. Look after
+ ;; inclusion lines too, as different parts of the same
+ ;; file can be included too.
+ ((and f (guard (member (list f (plist-get parameters :lines))
+ included)))
+ (error "Recursive file inclusion: %s" f))
+ (_
+ (org-export--blindly-expand-include
+ parameters
+ :includer-file includer-file
+ :file-prefix file-prefix
+ :footnotes footnotes
+ :already-included included)
+ ;; Expand footnotes after all files have been
+ ;; included. Footnotes are stored at end of buffer.
+ (unless included
+ (org-with-wide-buffer
+ (goto-char (point-max))
+ (maphash (lambda (k v)
+ (insert (format "\n[fn:%s] %s\n" k v)))
+ footnotes))))))))))))
+
+(defun org-export-parse-include-value (value &optional dir)
+ "Extract the various parameters from #+include: VALUE."
+ (let* ((ind (org-current-text-indentation))
+ location
+ (coding-system
+ (and (string-match ":coding +\\(\\S-+\\)>" value)
+ (prog1 (intern (match-string 1 value))
+ (setq value (replace-match "" nil nil value)))))
+ (file
+ (and (string-match "^\\(\".+?\"\\|\\S-+\\)\\(?:\\s-+\\|$\\)" value)
+ (prog1
+ (save-match-data
+ (let ((matched (match-string 1 value))
+ stripped)
+ (when (string-match "\\(::\\(.*?\\)\\)\"?\\'"
+ matched)
+ (setq location (match-string 2 matched))
+ (setq matched
+ (replace-match "" nil nil matched 1)))
+ (setq stripped (org-strip-quotes matched))
+ (if (org-url-p stripped)
+ stripped
+ (expand-file-name stripped dir))))
+ (setq value (replace-match "" nil nil value)))))
+ (only-contents
+ (and (string-match ":only-contents *\\([^: \r\t\n]\\S-*\\)?"
+ value)
+ (prog1 (org-not-nil (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 "\\<example\\>" value) 'literal)
+ ((string-match "\\<export\\(?: +\\(.*\\)\\)?" value)
+ 'literal)
+ ((string-match "\\<src\\(?: +\\(.*\\)\\)?" value)
+ 'literal)))
+ ;; Minimal level of included file defaults to the
+ ;; child level of the current headline, if any, or
+ ;; one. It only applies is the file is meant to be
+ ;; included as an Org one.
+ (minlevel
+ (and (not env)
+ (if (string-match ":minlevel +\\([0-9]+\\)" value)
+ (prog1 (string-to-number (match-string 1 value))
+ (setq value (replace-match "" nil nil value)))
+ (get-text-property (point)
+ :org-include-induced-level))))
+ (args (and (eq env 'literal) (match-string 1 value)))
+ (block (and (string-match "\\<\\(\\S-+\\)\\>" value)
+ (match-string 1 value))))
+ (list :file file
+ :coding-system coding-system
+ :location location
+ :only-contents only-contents
+ :lines lines
+ :env env
+ :minlevel minlevel
+ :args args
+ :block block)))
+
+(cl-defun org-export--blindly-expand-include (parameters &key includer-file
file-prefix footnotes already-included)
+ "Unconditionally include reference defined by PARAMETERS in the buffer.
+PARAMETERS is a plist of the form returned by `org-export-parse-include-value'.
+
+INCLUDER-FILE is a path to the file where the include keyword is
+being expanded. FILE-PREFIX is a hash-table of file and
+prefixes, which can be provided to ensure consistent prefixing.
+FOOTNOTES is a hash-table for storing and resolving footnotes,
+which when provided allows footnotes to be handled appropriately.
+ALREADY-INCLUDED is a list of included names along with their
+line restriction which prevents recursion."
+ (let* ((coding-system-for-read
+ (or (plist-get parameters :coding-system)
+ coding-system-for-read))
+ (file (plist-get parameters :file))
+ (lines (plist-get parameters :lines))
+ (args (plist-get parameters :args))
+ (block (plist-get parameters :block))
+ (ind (org-current-text-indentation)))
+ (cond
+ ((eq (plist-get parameters :env) 'literal)
+ (insert
+ (let ((ind-str (make-string ind ?\s))
+ (arg-str (if (stringp args) (format " %s" args) ""))
+ (contents
+ (org-escape-code-in-string
+ (org-export--prepare-file-contents file lines))))
+ (format "%s#+BEGIN_%s%s\n%s%s#+END_%s\n"
+ ind-str block arg-str contents ind-str block))))
+ ((stringp block)
+ (insert
+ (let ((ind-str (make-string ind ?\s))
+ (contents
+ (org-export--prepare-file-contents file lines)))
+ (format "%s#+BEGIN_%s\n%s%s#+END_%s\n"
+ ind-str block contents ind-str block))))
+ (t
+ (insert
+ (with-temp-buffer
+ (let ((org-inhibit-startup t)
+ (lines
+ (if-let ((location (plist-get parameters :location)))
+ (org-export--inclusion-absolute-lines
+ file location
+ (plist-get parameters :only-contents)
+ lines)
+ lines)))
+ (org-mode)
+ (insert
+ (org-export--prepare-file-contents
+ file lines ind (plist-get parameters :minlevel)
+ (and file-prefix
+ (or (gethash file file-prefix)
+ (puthash file
+ (hash-table-count file-prefix)
+ file-prefix)))
+ footnotes includer-file)))
+ (org-export-expand-include-keyword
+ (cons (list file lines) already-included)
+ (unless (org-url-p file)
+ (file-name-directory file))
+ footnotes includer-file)
+ (buffer-string)))))))
(defun org-export--inclusion-absolute-lines (file location only-contents lines)
"Resolve absolute lines for an included file with file-link.
- [elpa] externals/org updated (b34bdc8719 -> f0dfbf0c39), ELPA Syncer, 2023/01/22
- [elpa] externals/org ddca762329 01/14: org-element--cache-verify-element: Format all the elements in warning, ELPA Syncer, 2023/01/22
- [elpa] externals/org 0af74d33a7 03/14: org-manual: Fix typos in print_bibliography kwd, ELPA Syncer, 2023/01/22
- [elpa] externals/org ffd832d5d6 06/14: org-manual: Update #+include block parsing, ELPA Syncer, 2023/01/22
- [elpa] externals/org e9c0696f79 08/14: org-persist: Inhibit fsync when writing cachefiles, ELPA Syncer, 2023/01/22
- [elpa] externals/org 4b546e04af 02/14: org-element--cache-submit-request: Ensure correct cache synchronization, ELPA Syncer, 2023/01/22
- [elpa] externals/org 7e649050c7 05/14: ox: Pass through unparsed #+include content, ELPA Syncer, 2023/01/22
- [elpa] externals/org c8f88589cb 09/14: org-persist: Set utf-8 coding when reading/writing, ELPA Syncer, 2023/01/22
- [elpa] externals/org b29f772416 10/14: org-macs: Split org-compile-file into two funs, ELPA Syncer, 2023/01/22
- [elpa] externals/org f0dfbf0c39 14/14: ox-latex: Erase compile buffer at the start, ELPA Syncer, 2023/01/22
- [elpa] externals/org 5cde90e3c8 04/14: ox: Refactor org-export-expand-include-keyword,
ELPA Syncer <=
- [elpa] externals/org 506989bed5 07/14: ox: Improve #+include parsing docstring, ELPA Syncer, 2023/01/22
- [elpa] externals/org b84018633e 13/14: ox-latex: Split org-latex-compile into two funs, ELPA Syncer, 2023/01/22
- [elpa] externals/org d0c87c762a 11/14: ox-latex: Do not hardcode fallback compiler, ELPA Syncer, 2023/01/22
- [elpa] externals/org 18d2f871c2 12/14: org: Split org-format-latex into two functions, ELPA Syncer, 2023/01/22