mirror of
https://git.savannah.gnu.org/git/emacs/org-mode.git
synced 2025-01-03 11:33:46 +00:00
org-export: Fix bug with recursive file inclusion and relative paths
* contrib/lisp/org-export.el (org-export-expand-include-keyword): Use another optional argument to specify the current working directory. (org-export-as): Apply changes. * testing/contrib/lisp/test-org-export.el: Add tests. * testing/examples/include.org: New test file. * testing/examples/include2.org: New test file.
This commit is contained in:
parent
186f0f7594
commit
94185eac92
@ -2101,7 +2101,7 @@ Return code as a string."
|
||||
;; visible part of buffer.
|
||||
(if noexpand (org-element-parse-buffer nil visible-only)
|
||||
(org-export-with-current-buffer-copy
|
||||
(org-export-expand-include-keyword nil)
|
||||
(org-export-expand-include-keyword)
|
||||
(let ((org-current-export-file (current-buffer)))
|
||||
(org-export-blocks-preprocess))
|
||||
(org-element-parse-buffer nil visible-only)))
|
||||
@ -2250,14 +2250,16 @@ 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)
|
||||
(defun org-export-expand-include-keyword (&optional included dir)
|
||||
"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))
|
||||
Optional argument INCLUDED is a list of included file names along
|
||||
with their line restriction, when appropriate. It is used to
|
||||
avoid infinite recursion. Optional argument DIR is the current
|
||||
working directory. It is used to properly resolve relative
|
||||
paths."
|
||||
(let ((case-fold-search t))
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "^[ \t]*#\\+include: \\(.*\\)" nil t)
|
||||
(while (re-search-forward "^[ \t]*#\\+INCLUDE: \\(.*\\)" nil t)
|
||||
(when (eq (org-element-type (save-match-data (org-element-at-point)))
|
||||
'keyword)
|
||||
(beginning-of-line)
|
||||
@ -2265,7 +2267,7 @@ recursion."
|
||||
(let* ((value (match-string 1))
|
||||
(ind (org-get-indentation))
|
||||
(file (and (string-match "^\"\\(\\S-+\\)\"" value)
|
||||
(prog1 (expand-file-name (match-string 1 value))
|
||||
(prog1 (expand-file-name (match-string 1 value) dir)
|
||||
(setq value (replace-match "" nil nil value)))))
|
||||
(lines
|
||||
(and (string-match
|
||||
@ -2306,7 +2308,7 @@ recursion."
|
||||
"\\(^\\)\\([*]\\|[ \t]*#\\+\\)" ","
|
||||
(org-export-prepare-file-contents file lines)
|
||||
nil nil 1)))
|
||||
(format "%s#+begin_example\n%s%s#+end_example\n"
|
||||
(format "%s#+BEGIN_EXAMPLE\n%s%s#+END_EXAMPLE\n"
|
||||
ind-str contents ind-str))))
|
||||
((stringp env)
|
||||
(insert
|
||||
@ -2318,7 +2320,7 @@ recursion."
|
||||
"\\(^\\)\\([*]\\|[ \t]*#\\+\\)") ","
|
||||
(org-export-prepare-file-contents file lines)
|
||||
nil nil 1)))
|
||||
(format "%s#+begin_src %s\n%s%s#+end_src\n"
|
||||
(format "%s#+BEGIN_SRC %s\n%s%s#+END_SRC\n"
|
||||
ind-str env contents ind-str))))
|
||||
(t
|
||||
(insert
|
||||
@ -2327,7 +2329,8 @@ recursion."
|
||||
(insert
|
||||
(org-export-prepare-file-contents file lines ind minlevel))
|
||||
(org-export-expand-include-keyword
|
||||
(cons (list file lines) included))
|
||||
(cons (list file lines) included)
|
||||
(file-name-directory file))
|
||||
(buffer-string))))))))))))
|
||||
|
||||
(defun org-export-prepare-file-contents (file &optional lines ind minlevel)
|
||||
|
@ -247,3 +247,52 @@ text
|
||||
(should (equal (org-export-as 'test) "A\n")))
|
||||
(let ((org-export-snippet-translation-alist '(("t" . "test"))))
|
||||
(should (equal (org-export-as 'test) "AB\n")))))))
|
||||
|
||||
(ert-deftest test-org-export/expand-include ()
|
||||
"Test file inclusion in an Org buffer."
|
||||
;; Full insertion with recursive inclusion.
|
||||
(org-test-with-temp-text
|
||||
(format "#+INCLUDE: \"%s/examples/include.org\"" org-test-dir)
|
||||
(org-export-expand-include-keyword)
|
||||
(should (equal (buffer-string)
|
||||
"Small Org file with an include keyword.
|
||||
|
||||
#+BEGIN_SRC emacs-lisp :exports results
|
||||
(+ 2 1)
|
||||
#+END_SRC
|
||||
|
||||
Success!
|
||||
|
||||
* Heading
|
||||
body\n")))
|
||||
;; Localized insertion.
|
||||
(org-test-with-temp-text
|
||||
(format "#+INCLUDE: \"%s/examples/include.org\" :lines \"1-2\""
|
||||
org-test-dir)
|
||||
(org-export-expand-include-keyword)
|
||||
(should (equal (buffer-string)
|
||||
"Small Org file with an include keyword.\n")))
|
||||
;; Insertion with constraints on headlines level.
|
||||
(org-test-with-temp-text
|
||||
(format
|
||||
"* Top heading\n#+INCLUDE: \"%s/examples/include.org\" :lines \"9-\""
|
||||
org-test-dir)
|
||||
(org-export-expand-include-keyword)
|
||||
(should (equal (buffer-string) "* Top heading\n** Heading\nbody\n")))
|
||||
;; Inclusion within an example block.
|
||||
(org-test-with-temp-text
|
||||
(format "#+INCLUDE: \"%s/examples/include.org\" :lines \"1-2\" example"
|
||||
org-test-dir)
|
||||
(org-export-expand-include-keyword)
|
||||
(should
|
||||
(equal
|
||||
(buffer-string)
|
||||
"#+BEGIN_EXAMPLE\nSmall Org file with an include keyword.\n#+END_EXAMPLE\n")))
|
||||
;; Inclusion within a src-block.
|
||||
(org-test-with-temp-text
|
||||
(format
|
||||
"#+INCLUDE: \"%s/examples/include.org\" :lines \"4-5\" src emacs-lisp"
|
||||
org-test-dir)
|
||||
(org-export-expand-include-keyword)
|
||||
(should (equal (buffer-string)
|
||||
"#+BEGIN_SRC emacs-lisp\n(+ 2 1)\n#+END_SRC\n"))))
|
||||
|
10
testing/examples/include.org
Normal file
10
testing/examples/include.org
Normal file
@ -0,0 +1,10 @@
|
||||
Small Org file with an include keyword.
|
||||
|
||||
#+BEGIN_SRC emacs-lisp :exports results
|
||||
(+ 2 1)
|
||||
#+END_SRC
|
||||
|
||||
#+INCLUDE: "include2.org"
|
||||
|
||||
* Heading
|
||||
body
|
1
testing/examples/include2.org
Normal file
1
testing/examples/include2.org
Normal file
@ -0,0 +1 @@
|
||||
Success!
|
Loading…
Reference in New Issue
Block a user