Browse Source

ox: Add EXPORT_FILE_NAME keyword

* lisp/ox.el (org-export-output-file-name): Support EXPORT_FILE_NAME
  keyword.
* doc/org.texi (Export settings): Document new keyword.
* testing/lisp/test-ox.el (test-org-export/output-file-name): Add
  tests.
Nicolas Goaziou 8 years ago
parent
commit
91dc1b34e3
4 changed files with 77 additions and 44 deletions
  1. 9 10
      doc/org.texi
  2. 4 0
      etc/ORG-NEWS
  3. 26 18
      lisp/ox.el
  4. 38 16
      testing/lisp/test-ox.el

+ 9 - 10
doc/org.texi

@@ -10465,6 +10465,12 @@ be executed during export even though the subtree is not exported.
 The title to be shown.  You can use several such keywords for long titles.
 @end table
 
+@item EXPORT_FILE_NAME
+@cindex #+EXPORT_FILE_NAME
+The name of the output file to be generated.  By default, it is taken from
+the file associated to the buffer, when possible, or asked to you otherwise.
+In all cases, the extension is ignored, and a back-end specific one is added.
+
 The @code{#+OPTIONS} keyword is a compact@footnote{If you want to configure
 many options this way, you can use several @code{#+OPTIONS} lines.} form that
 recognizes the following arguments:
@@ -10636,9 +10642,9 @@ Toggle inclusion of tables (@code{org-export-with-tables}).
 When exporting only a subtree, each of the previous keywords@footnote{With
 the exception of @samp{SETUPFILE}.} can be overridden locally by special node
 properties.  These begin with @samp{EXPORT_}, followed by the name of the
-keyword they supplant.  For example, @samp{DATE} and @samp{OPTIONS} keywords
-become, respectively, @samp{EXPORT_DATE} and @samp{EXPORT_OPTIONS}
-properties.
+keyword they supplant, unless the keyword already beging with @samp{EXPORT_}.
+For example, @samp{DATE} and @samp{EXPORT_FILE_NAME} keywords become,
+respectively, @samp{EXPORT_DATE} and @samp{EXPORT_FILE_NAME} properties.
 
 @cindex #+BIND
 @vindex org-export-allow-bind-keywords
@@ -10647,13 +10653,6 @@ can become buffer-local during export by using the BIND keyword.  Its syntax
 is @samp{#+BIND: variable value}.  This is particularly useful for in-buffer
 settings that cannot be changed using specific keywords.
 
-@cindex property, EXPORT_FILE_NAME
-The name of the output file to be generated is taken from the file associated
-to the buffer, when possible, or asked to you otherwise.  For subtree export,
-you can also set @code{EXPORT_FILE_NAME} property.  In all cases, only the
-base name of the file is retained, and a back-end specific extension is
-added.
-
 @node Table of contents
 @section Table of contents
 @cindex table of contents

+ 4 - 0
etc/ORG-NEWS

@@ -128,6 +128,10 @@ as descriptions of links, a.k.a. image links.  See its docstring for
 details.
 **** Add global macros through ~org-export-global-macros~ 
 With this variable, one can define macros available for all documents.
+**** New keyword ~#+EXPORT_FILE_NAME~
+Simiralry to ~:EXPORT_FILE_NAME:~ property, this keyword allow to
+specify the name of the output file upon exporting the document.  This
+has also an effect on publishing.
 **** Horizontal rules are no longer ignored in LaTeX table math mode
 
 *** ~org-list-to-generic~ includes a new property: ~:ifmt~

+ 26 - 18
lisp/ox.el

@@ -6184,29 +6184,37 @@ directory.
 Return file name as a string."
   (let* ((visited-file (buffer-file-name (buffer-base-buffer)))
 	 (base-name
-	  ;; File name may come from EXPORT_FILE_NAME subtree
-	  ;; property.
-	  (file-name-sans-extension
-	   (or (and subtreep (org-entry-get nil "EXPORT_FILE_NAME" 'selective))
-	       ;; File name may be extracted from buffer's associated
-	       ;; file, if any.
-	       (and visited-file (file-name-nondirectory visited-file))
-	       ;; Can't determine file name on our own: Ask user.
-	       (read-file-name
-		"Output file: " pub-dir nil nil nil
-		(lambda (name)
-		  (string= (file-name-extension name t) extension))))))
+	  (concat
+	   (file-name-sans-extension
+	    (or
+	     ;; Check EXPORT_FILE_NAME subtree property.
+	     (and subtreep (org-entry-get nil "EXPORT_FILE_NAME" 'selective))
+	     ;; Check #+EXPORT_FILE_NAME keyword.
+	     (org-with-point-at (point-min)
+	       (catch :found
+		 (let ((case-fold-search t))
+		   (while (re-search-forward
+			   "^[ \t]*#\\+EXPORT_FILE_NAME:[ \t]+\\S-" nil t)
+		     (let ((element (org-element-at-point)))
+		       (when (eq 'keyword (org-element-type element))
+			 (throw :found
+				(org-element-property :value element))))))))
+	     ;; Extract from buffer's associated file, if any.
+	     (and visited-file (file-name-nondirectory visited-file))
+	     ;; Can't determine file name on our own: ask user.
+	     (read-file-name
+	      "Output file: " pub-dir nil nil nil
+	      (lambda (n) (string= extension (file-name-extension n t))))))
+	   extension))
 	 (output-file
 	  ;; Build file name.  Enforce EXTENSION over whatever user
 	  ;; may have come up with.  PUB-DIR, if defined, always has
 	  ;; precedence over any provided path.
 	  (cond
-	   (pub-dir
-	    (concat (file-name-as-directory pub-dir)
-		    (file-name-nondirectory base-name)
-		    extension))
-	   ((file-name-absolute-p base-name) (concat base-name extension))
-	   (t (concat (file-name-as-directory ".") base-name extension)))))
+	   (pub-dir (concat (file-name-as-directory pub-dir)
+			    (file-name-nondirectory base-name)))
+	   ((file-name-absolute-p base-name) base-name)
+	   (t base-name))))
     ;; If writing to OUTPUT-FILE would overwrite original file, append
     ;; EXTENSION another time to final name.
     (if (and visited-file (file-equal-p visited-file output-file))

+ 38 - 16
testing/lisp/test-ox.el

@@ -961,20 +961,34 @@ Text"
   ;; Export from a file: name is built from original file name.
   (should
    (org-test-with-temp-text-in-file "Test"
-     (equal (concat (file-name-as-directory ".")
-		    (file-name-nondirectory
-		     (file-name-sans-extension (buffer-file-name))))
-	    (file-name-sans-extension (org-export-output-file-name ".ext")))))
+     (equal (file-name-base (buffer-file-name))
+	    (file-name-base (org-export-output-file-name ".ext")))))
+  ;; When #+EXPORT_FILE_NAME is defined, use it.
+  (should
+   (equal "test.ext"
+	  (org-test-with-temp-text-in-file "#+EXPORT_FILE_NAME: test"
+	    (org-export-output-file-name ".ext" t))))
   ;; When exporting to subtree, check EXPORT_FILE_NAME property first.
   (should
-   (org-test-with-temp-text-in-file
-       "* Test\n  :PROPERTIES:\n  :EXPORT_FILE_NAME: test\n  :END:"
-     (equal (org-export-output-file-name ".ext" t) "./test.ext")))
+   (equal "test.ext"
+	  (org-test-with-temp-text-in-file
+	      "* Test\n  :PROPERTIES:\n  :EXPORT_FILE_NAME: test\n  :END:"
+	    (org-export-output-file-name ".ext" t))))
+  (should
+   (equal "property.ext"
+	  (org-test-with-temp-text
+	      "#+EXPORT_FILE_NAME: keyword
+* Test<point>
+:PROPERTIES:
+:EXPORT_FILE_NAME: property
+:END:"
+	    (org-export-output-file-name ".ext" t))))
   ;; From a buffer not associated to a file, too.
   (should
-   (org-test-with-temp-text
-       "* Test\n  :PROPERTIES:\n  :EXPORT_FILE_NAME: test\n  :END:"
-     (equal (org-export-output-file-name ".ext" t) "./test.ext")))
+   (equal "test.ext"
+	  (org-test-with-temp-text
+	      "* Test\n  :PROPERTIES:\n  :EXPORT_FILE_NAME: test\n  :END:"
+	    (org-export-output-file-name ".ext" t))))
   ;; When provided name is absolute, preserve it.
   (should
    (org-test-with-temp-text
@@ -983,15 +997,23 @@ Text"
      (file-name-absolute-p (org-export-output-file-name ".ext" t))))
   ;; When PUB-DIR argument is provided, use it.
   (should
-   (org-test-with-temp-text-in-file "Test"
-     (equal (file-name-directory
-	     (org-export-output-file-name ".ext" nil "dir/"))
-	    "dir/")))
+   (equal "dir/"
+	  (org-test-with-temp-text-in-file "Test"
+	    (file-name-directory
+	     (org-export-output-file-name ".ext" nil "dir/")))))
+  ;; PUB-DIR has precedence over EXPORT_FILE_NAME keyword or property.
+  (should
+   (equal "pub-dir/"
+	  (org-test-with-temp-text-in-file
+	      "#+EXPORT_FILE_NAME: /dir/keyword\nTest"
+	    (file-name-directory
+	     (org-export-output-file-name ".ext" nil "pub-dir/")))))
   ;; When returned name would overwrite original file, add EXTENSION
   ;; another time.
   (should
-   (org-test-at-id "75282ba2-f77a-4309-a970-e87c149fe125"
-     (equal (org-export-output-file-name ".org") "./normal.org.org"))))
+   (equal "normal.org.org"
+	  (org-test-at-id "75282ba2-f77a-4309-a970-e87c149fe125"
+	    (org-export-output-file-name ".org")))))
 
 (ert-deftest test-org-export/expand-include ()
   "Test file inclusion in an Org buffer."