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.
 The title to be shown.  You can use several such keywords for long titles.
 @end table
 @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
 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
 many options this way, you can use several @code{#+OPTIONS} lines.} form that
 recognizes the following arguments:
 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
 When exporting only a subtree, each of the previous keywords@footnote{With
 the exception of @samp{SETUPFILE}.} can be overridden locally by special node
 the exception of @samp{SETUPFILE}.} can be overridden locally by special node
 properties.  These begin with @samp{EXPORT_}, followed by the name of the
 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
 @cindex #+BIND
 @vindex org-export-allow-bind-keywords
 @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
 is @samp{#+BIND: variable value}.  This is particularly useful for in-buffer
 settings that cannot be changed using specific keywords.
 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
 @node Table of contents
 @section Table of contents
 @section Table of contents
 @cindex 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.
 details.
 **** Add global macros through ~org-export-global-macros~ 
 **** Add global macros through ~org-export-global-macros~ 
 With this variable, one can define macros available for all documents.
 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
 **** Horizontal rules are no longer ignored in LaTeX table math mode
 
 
 *** ~org-list-to-generic~ includes a new property: ~:ifmt~
 *** ~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."
 Return file name as a string."
   (let* ((visited-file (buffer-file-name (buffer-base-buffer)))
   (let* ((visited-file (buffer-file-name (buffer-base-buffer)))
 	 (base-name
 	 (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
 	 (output-file
 	  ;; Build file name.  Enforce EXTENSION over whatever user
 	  ;; Build file name.  Enforce EXTENSION over whatever user
 	  ;; may have come up with.  PUB-DIR, if defined, always has
 	  ;; may have come up with.  PUB-DIR, if defined, always has
 	  ;; precedence over any provided path.
 	  ;; precedence over any provided path.
 	  (cond
 	  (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
     ;; If writing to OUTPUT-FILE would overwrite original file, append
     ;; EXTENSION another time to final name.
     ;; EXTENSION another time to final name.
     (if (and visited-file (file-equal-p visited-file output-file))
     (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.
   ;; Export from a file: name is built from original file name.
   (should
   (should
    (org-test-with-temp-text-in-file "Test"
    (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.
   ;; When exporting to subtree, check EXPORT_FILE_NAME property first.
   (should
   (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.
   ;; From a buffer not associated to a file, too.
   (should
   (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.
   ;; When provided name is absolute, preserve it.
   (should
   (should
    (org-test-with-temp-text
    (org-test-with-temp-text
@@ -983,15 +997,23 @@ Text"
      (file-name-absolute-p (org-export-output-file-name ".ext" t))))
      (file-name-absolute-p (org-export-output-file-name ".ext" t))))
   ;; When PUB-DIR argument is provided, use it.
   ;; When PUB-DIR argument is provided, use it.
   (should
   (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
   ;; When returned name would overwrite original file, add EXTENSION
   ;; another time.
   ;; another time.
   (should
   (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 ()
 (ert-deftest test-org-export/expand-include ()
   "Test file inclusion in an Org buffer."
   "Test file inclusion in an Org buffer."