From e09ffe2a678e2f8a095eb16ec4fbba5eedc34d78 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Wed, 25 Sep 2013 21:27:29 +0200 Subject: [PATCH] ox: Add a defcustom to export properties drawers * lisp/ox.el (org-export-with-drawers): Improve docstring. (org-export-with-properties): New variable (org-export--skip-p): Handle new variable. (org-export-options-alist): Install new variable. * lisp/ox-ascii.el (org-ascii-node-property, org-ascii-property-drawer): New functions. * lisp/ox-html.el (org-html-node-property): New function. (org-html-property-drawer): Export property drawers as "pre" blocks. * lisp/ox-latex.el (org-latex-property-drawer, org-latex-node-property): New functions. * lisp/ox-man.el (org-man-node-property, org-man-property-drawer): New functions. * lisp/ox-md.el (org-md-node-property, org-md-property-drawer): New functions. * lisp/ox-odt.el (org-odt-node-property): New function. (org-odt-property-drawer): Export property drawers as fixed width blocks. * lisp/ox-texinfo.el (org-texinfo-node-property): New function. (org-texinfo-property-drawer): Export property drawers as verbatim blocks. * doc/org.texi: Update manual. * testing/lisp/test-ox.el: Add tests. --- doc/org.texi | 20 +++++++++++++++++++- lisp/ox-ascii.el | 23 +++++++++++++++++++++++ lisp/ox-html.el | 21 ++++++++++++++++----- lisp/ox-latex.el | 25 ++++++++++++++++++++++++- lisp/ox-man.el | 19 ++++++++++++++++++- lisp/ox-md.el | 24 ++++++++++++++++++++++++ lisp/ox-odt.el | 23 ++++++++++++++++++----- lisp/ox-texinfo.el | 21 ++++++++++++++++----- lisp/ox.el | 32 +++++++++++++++++++++++++++++--- testing/lisp/test-ox.el | 19 +++++++++++++++++++ 10 files changed, 206 insertions(+), 21 deletions(-) diff --git a/doc/org.texi b/doc/org.texi index e1cb01719..4ca058820 100644 --- a/doc/org.texi +++ b/doc/org.texi @@ -10461,6 +10461,7 @@ Other back-ends might be found in the @code{contrib/} directory @section Export settings @cindex Export, settings +@cindex #+OPTIONS Export options can be set: globally with variables; for an individual file by making variables buffer-local with in-buffer settings (@pxref{In-buffer settings}), by setting individual keywords, or by specifying them in a @@ -10482,34 +10483,41 @@ variables, include: @table @samp @item AUTHOR +@cindex #+AUTHOR @vindex user-full-name The document author (@code{user-full-name}). @item CREATOR +@cindex #+CREATOR @vindex org-export-creator-string Entity responsible for output generation (@code{org-export-creator-string}). @item DATE +@cindex #+DATE @vindex org-export-date-timestamp-format A date or a time-stamp@footnote{The variable @code{org-export-date-timestamp-format} defines how this time-stamp will be exported.}. @item DESCRIPTION +@cindex #+DESCRIPTION The document description. Back-ends handle it as they see fit (e.g., for the XHTML meta tag), if at all. You can use several such keywords for long descriptions. @item EMAIL +@cindex #+EMAIL @vindex user-mail-address The email address (@code{user-mail-address}). @item KEYWORDS +@cindex #+KEYWORDS The keywords defining the contents of the document. Back-ends handle it as they see fit (e.g., for the XHTML meta tag), if at all. You can use several such keywords if the list is long. @item LANGUAGE +@cindex #+LANGUAGE @vindex org-export-default-language The language used for translating some strings (@code{org-export-default-language}). E.g., @samp{#+LANGUAGE: fr} will tell @@ -10517,6 +10525,7 @@ Org to translate @emph{File} (english) into @emph{Fichier} (french) in the clocktable. @item SELECT_TAGS +@cindex #+SELECT_TAGS @vindex org-export-select-tags The tags that select a tree for export (@code{org-export-select-tags}). The default value is @code{:export:}. Within a subtree tagged with @@ -10524,12 +10533,15 @@ default value is @code{:export:}. Within a subtree tagged with below). @item EXCLUDE_TAGS +@cindex #+EXCLUDE_TAGS +@vindex org-export-exclude-tags The tags that exclude a tree from export (@code{org-export-exclude-tags}). The default value is @code{:noexport:}. Entries with the @code{:noexport:} tag will be unconditionally excluded from the export, even if they have an @code{:export:} tag. @item TITLE +@cindex #+TITLE The title to be shown (otherwise derived from buffer's name). You can use several such keywords for long titles. @end table @@ -10635,6 +10647,11 @@ Toggle export of planning information (@code{org-export-with-planning}). @vindex org-export-with-priority Toggle inclusion of priority cookies (@code{org-export-with-priority}). +@item prop: +@vindex org-export-with-properties +Toggle inclusion of property drawers, or list properties to include +(@code{org-export-with-properties}). + @item stat: @vindex org-export-with-statistics-cookies Toggle inclusion of statistics cookies @@ -13293,6 +13310,7 @@ string of these options for details. @vindex org-export-with-latex @vindex org-export-with-planning @vindex org-export-with-priority +@vindex org-export-with-properties @vindex org-export-with-section-numbers @vindex org-export-with-special-strings @vindex org-export-with-sub-superscripts @@ -13303,7 +13321,6 @@ string of these options for details. @vindex org-export-with-toc @vindex org-export-with-todo-keywords @vindex user-mail-address - @multitable @columnfractions 0.32 0.68 @item @code{:archived-trees} @tab @code{org-export-with-archived-trees} @item @code{:exclude-tags} @tab @code{org-export-exclude-tags} @@ -13323,6 +13340,7 @@ string of these options for details. @item @code{:with-latex} @tab @code{org-export-with-latex} @item @code{:with-planning} @tab @code{org-export-with-planning} @item @code{:with-priority} @tab @code{org-export-with-priority} +@item @code{:with-properties} @tab @code{org-export-with-properties} @item @code{:with-special-strings} @tab @code{org-export-with-special-strings} @item @code{:with-sub-superscript} @tab @code{org-export-with-sub-superscripts} @item @code{:with-tables} @tab @code{org-export-with-tables} diff --git a/lisp/ox-ascii.el b/lisp/ox-ascii.el index 74a7c6481..e0a3fa913 100644 --- a/lisp/ox-ascii.el +++ b/lisp/ox-ascii.el @@ -81,10 +81,12 @@ (latex-fragment . org-ascii-latex-fragment) (line-break . org-ascii-line-break) (link . org-ascii-link) + (node-property . org-ascii-node-property) (paragraph . org-ascii-paragraph) (plain-list . org-ascii-plain-list) (plain-text . org-ascii-plain-text) (planning . org-ascii-planning) + (property-drawer . org-ascii-property-drawer) (quote-block . org-ascii-quote-block) (quote-section . org-ascii-quote-section) (radio-target . org-ascii-radio-target) @@ -1440,6 +1442,18 @@ INFO is a plist holding contextual information." (unless org-ascii-links-to-notes (format " (%s)" raw-link)))))))) +;;;; Node Properties + +(defun org-ascii-node-property (node-property contents info) + "Transcode a NODE-PROPERTY element from Org to ASCII. +CONTENTS is nil. INFO is a plist holding contextual +information." + (format "%s:%s" + (org-element-property :key node-property) + (let ((value (org-element-property :value node-property))) + (if value (concat " " value) "")))) + + ;;;; Paragraph (defun org-ascii-paragraph (paragraph contents info) @@ -1509,6 +1523,15 @@ channel." " ")) +;;;; Property Drawer + +(defun org-ascii-property-drawer (property-drawer contents info) + "Transcode a PROPERTY-DRAWER element from Org to ASCII. +CONTENTS holds the contents of the drawer. INFO is a plist +holding contextual information." + (org-string-nw-p contents)) + + ;;;; Quote Block (defun org-ascii-quote-block (quote-block contents info) diff --git a/lisp/ox-html.el b/lisp/ox-html.el index 14b31b27b..66862bcad 100644 --- a/lisp/ox-html.el +++ b/lisp/ox-html.el @@ -76,6 +76,7 @@ (latex-fragment . org-html-latex-fragment) (line-break . org-html-line-break) (link . org-html-link) + (node-property . org-html-node-property) (paragraph . org-html-paragraph) (plain-list . org-html-plain-list) (plain-text . org-html-plain-text) @@ -2782,6 +2783,17 @@ INFO is a plist holding contextual information. See ;; No path, only description. Try to do something useful. (t (format "%s" desc))))) +;;;; Node Property + +(defun org-html-node-property (node-property contents info) + "Transcode a NODE-PROPERTY element from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual +information." + (format "%s:%s" + (org-element-property :key node-property) + (let ((value (org-element-property :value node-property))) + (if value (concat " " value) "")))) + ;;;; Paragraph (defun org-html-paragraph (paragraph contents info) @@ -2930,11 +2942,10 @@ channel." (defun org-html-property-drawer (property-drawer contents info) "Transcode a PROPERTY-DRAWER element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual -information." - ;; The property drawer isn't exported but we want separating blank - ;; lines nonetheless. - "") +CONTENTS holds the contents of the drawer. INFO is a plist +holding contextual information." + (and (org-string-nw-p contents) + (format "
\n%s
" contents))) ;;;; Quote Block diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index e1173efa8..196e50f94 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -63,11 +63,12 @@ (latex-fragment . org-latex-latex-fragment) (line-break . org-latex-line-break) (link . org-latex-link) + (node-property . org-latex-node-property) (paragraph . org-latex-paragraph) (plain-list . org-latex-plain-list) (plain-text . org-latex-plain-text) (planning . org-latex-planning) - (property-drawer . (lambda (&rest args) "")) + (property-drawer . org-latex-property-drawer) (quote-block . org-latex-quote-block) (quote-section . org-latex-quote-section) (radio-target . org-latex-radio-target) @@ -1837,6 +1838,18 @@ INFO is a plist holding contextual information. See (t (format org-latex-link-with-unknown-path-format desc))))) +;;;; Node Property + +(defun org-latex-node-property (node-property contents info) + "Transcode a NODE-PROPERTY element from Org to LaTeX. +CONTENTS is nil. INFO is a plist holding contextual +information." + (format "%s:%s" + (org-element-property :key node-property) + (let ((value (org-element-property :value node-property))) + (if value (concat " " value) "")))) + + ;;;; Paragraph (defun org-latex-paragraph (paragraph contents info) @@ -1961,6 +1974,16 @@ information." "\\\\")) +;;;; Property Drawer + +(defun org-latex-property-drawer (property-drawer contents info) + "Transcode a PROPERTY-DRAWER element from Org to LaTeX. +CONTENTS holds the contents of the drawer. INFO is a plist +holding contextual information." + (and (org-string-nw-p contents) + (format "\\begin{verbatim}\n%s\\end{verbatim}" contents))) + + ;;;; Quote Block (defun org-latex-quote-block (quote-block contents info) diff --git a/lisp/ox-man.el b/lisp/ox-man.el index a160e4cff..760e264ce 100644 --- a/lisp/ox-man.el +++ b/lisp/ox-man.el @@ -76,11 +76,12 @@ (keyword . org-man-keyword) (line-break . org-man-line-break) (link . org-man-link) + (node-property . org-man-node-property) (paragraph . org-man-paragraph) (plain-list . org-man-plain-list) (plain-text . org-man-plain-text) (planning . org-man-planning) - (property-drawer . (lambda (&rest args) "")) + (property-drawer . org-man-property-drawer) (quote-block . org-man-quote-block) (quote-section . org-man-quote-section) (radio-target . org-man-radio-target) @@ -663,6 +664,16 @@ INFO is a plist holding contextual information. See ;; No path, only description. Try to do something useful. (t (format "\\fI%s\\fP" desc))))) +;;;; Node Property + +(defun org-man-node-property (node-property contents info) + "Transcode a NODE-PROPERTY element from Org to Man. +CONTENTS is nil. INFO is a plist holding contextual +information." + (format "%s:%s" + (org-element-property :key node-property) + (let ((value (org-element-property :value node-property))) + (if value (concat " " value) "")))) ;;; Paragraph @@ -722,6 +733,12 @@ contextual information." ;;; Property Drawer +(defun org-man-property-drawer (property-drawer contents info) + "Transcode a PROPERTY-DRAWER element from Org to Man. +CONTENTS holds the contents of the drawer. INFO is a plist +holding contextual information." + (and (org-string-nw-p contents) + (format ".RS\n.nf\n%s\n.fi\n.RE" contents))) ;;; Quote Block diff --git a/lisp/ox-md.el b/lisp/ox-md.el index feb611c6e..1114c50ef 100644 --- a/lisp/ox-md.el +++ b/lisp/ox-md.el @@ -82,9 +82,11 @@ This variable can be set to either `atx' or `setext'." (item . org-md-item) (line-break . org-md-line-break) (link . org-md-link) + (node-property . org-md-node-property) (paragraph . org-md-paragraph) (plain-list . org-md-plain-list) (plain-text . org-md-plain-text) + (property-drawer . org-md-property-drawer) (quote-block . org-md-quote-block) (quote-section . org-md-example-block) (section . org-md-section) @@ -334,6 +336,18 @@ a communication channel." (format "[%s](%s)" contents path))))))) +;;;; Node Property + +(defun org-md-node-property (node-property contents info) + "Transcode a NODE-PROPERTY element into Markdown syntax. +CONTENTS is nil. INFO is a plist holding contextual +information." + (format "%s:%s" + (org-element-property :key node-property) + (let ((value (org-element-property :value node-property))) + (if value (concat " " value) "")))) + + ;;;; Paragraph (defun org-md-paragraph (paragraph contents info) @@ -382,6 +396,16 @@ contextual information." text) +;;;; Property Drawer + +(defun org-md-property-drawer (property-drawer contents info) + "Transcode a PROPERTY-DRAWER element into Markdown format. +CONTENTS holds the contents of the drawer. INFO is a plist +holding contextual information." + (and (org-string-nw-p contents) + (replace-regexp-in-string "^" " " contents))) + + ;;;; Quote Block (defun org-md-quote-block (quote-block contents info) diff --git a/lisp/ox-odt.el b/lisp/ox-odt.el index ae9e4732f..57a9b6e20 100644 --- a/lisp/ox-odt.el +++ b/lisp/ox-odt.el @@ -59,6 +59,7 @@ (latex-fragment . org-odt-latex-fragment) (line-break . org-odt-line-break) (link . org-odt-link) + (node-property . org-odt-node-property) (paragraph . org-odt-paragraph) (plain-list . org-odt-plain-list) (plain-text . org-odt-plain-text) @@ -2868,6 +2869,18 @@ INFO is a plist holding contextual information. See "Emphasis" desc))))) +;;;; Node Property + +(defun org-odt-node-property (node-property contents info) + "Transcode a NODE-PROPERTY element from Org to ODT. +CONTENTS is nil. INFO is a plist holding contextual +information." + (org-odt--encode-plain-text + (format "%s:%s" + (org-element-property :key node-property) + (let ((value (org-element-property :value node-property))) + (if value (concat " " value) ""))))) + ;;;; Paragraph (defun org-odt--format-paragraph (paragraph contents default center quote) @@ -3005,11 +3018,11 @@ channel." (defun org-odt-property-drawer (property-drawer contents info) "Transcode a PROPERTY-DRAWER element from Org to ODT. -CONTENTS is nil. INFO is a plist holding contextual -information." - ;; The property drawer isn't exported but we want separating blank - ;; lines nonetheless. - "") +CONTENTS holds the contents of the drawer. INFO is a plist +holding contextual information." + (and (org-string-nw-p contents) + (format "%s" + contents))) ;;;; Quote Block diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el index d289e60ed..c834087f0 100644 --- a/lisp/ox-texinfo.el +++ b/lisp/ox-texinfo.el @@ -89,6 +89,7 @@ (keyword . org-texinfo-keyword) (line-break . org-texinfo-line-break) (link . org-texinfo-link) + (node-property . org-texinfo-node-property) (paragraph . org-texinfo-paragraph) (plain-list . org-texinfo-plain-list) (plain-text . org-texinfo-plain-text) @@ -1294,6 +1295,17 @@ are generated directly." ;;(org-texinfo--build-detailed-menu parse top info) (org-texinfo--build-menu parse 1 info 'detailed))))) +;;;; Node Property + +(defun org-texinfo-node-property (node-property contents info) + "Transcode a NODE-PROPERTY element from Org to Texinfo. +CONTENTS is nil. INFO is a plist holding contextual +information." + (format "%s:%s" + (org-element-property :key node-property) + (let ((value (org-element-property :value node-property))) + (if value (concat " " value) "")))) + ;;; Paragraph (defun org-texinfo-paragraph (paragraph contents info) @@ -1398,11 +1410,10 @@ information." (defun org-texinfo-property-drawer (property-drawer contents info) "Transcode a PROPERTY-DRAWER element from Org to Texinfo. -CONTENTS is nil. INFO is a plist holding contextual -information." - ;; The property drawer isn't exported but we want separating blank - ;; lines nonetheless. - "") +CONTENTS holds the contents of the drawer. INFO is a plist +holding contextual information." + (and (org-string-nw-p contents) + (format "@verbatim\n%s@end verbatim" contents))) ;;; Quote Block diff --git a/lisp/ox.el b/lisp/ox.el index 6c593687c..343c4ef21 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -128,6 +128,7 @@ (:with-latex nil "tex" org-export-with-latex) (:with-planning nil "p" org-export-with-planning) (:with-priority nil "pri" org-export-with-priority) + (:with-properties nil "prop" org-export-with-properties) (:with-smart-quotes nil "'" org-export-with-smart-quotes) (:with-special-strings nil "-" org-export-with-special-strings) (:with-statistics-cookies nil "stat" org-export-with-statistics-cookies) @@ -396,10 +397,11 @@ This option can also be set on with the CREATOR keyword." "Non-nil means export contents of standard drawers. When t, all drawers are exported. This may also be a list of -drawer names to export. If that list starts with `not', only -drawers with such names will be ignored. +drawer names to export, as strings. If that list starts with +`not', only drawers with such names will be ignored. -This variable doesn't apply to properties drawers. +This variable doesn't apply to properties drawers. See +`org-export-with-properties' instead. This option can also be set with the OPTIONS keyword, e.g. \"d:nil\"." @@ -557,6 +559,23 @@ e.g. \"pri:t\"." :group 'org-export-general :type 'boolean) +(defcustom org-export-with-properties nil + "Non-nil means export contents of properties drawers. + +When t, all properties are exported. This may also be a list of +properties to export, as strings. + +This option can also be set with the OPTIONS keyword, +e.g. \"prop:t\"." + :group 'org-export-general + :version "24.4" + :package-version '(Org . "8.3") + :type '(choice + (const :tag "All properties" t) + (const :tag "None" nil) + (repeat :tag "Selected properties" + (string :tag "Property name")))) + (defcustom org-export-with-section-numbers t "Non-nil means add section numbers to headlines when exporting. @@ -2072,7 +2091,14 @@ a tree with a select tag." (not (eq todo-type with-tasks))) (and (consp with-tasks) (not (member todo with-tasks)))))))) ((latex-environment latex-fragment) (not (plist-get options :with-latex))) + (node-property + (let ((properties-set (plist-get options :with-properties))) + (cond ((null properties-set) t) + ((consp properties-set) + (not (member-ignore-case (org-element-property :key blob) + properties-set)))))) (planning (not (plist-get options :with-planning))) + (property-drawer (not (plist-get options :with-properties))) (statistics-cookie (not (plist-get options :with-statistics-cookies))) (table-cell (and (org-export-table-has-special-column-p diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el index 54248cb3f..47c68d713 100644 --- a/testing/lisp/test-ox.el +++ b/testing/lisp/test-ox.el @@ -479,6 +479,25 @@ Paragraph" (org-test-with-temp-text "CLOSED: [2012-04-29 sun. 10:45]" (org-export-as (org-test-default-backend) nil nil nil '(:with-planning nil)))))) + ;; Property Drawers. + (should + (equal "* H1\n" + (org-test-with-temp-text + "* H1\n :PROPERTIES:\n :PROP: value\n :END:" + (org-export-as (org-test-default-backend) + nil nil nil '(:with-properties nil))))) + (should + (equal "* H1\n:PROPERTIES:\n:PROP: value\n:END:\n" + (org-test-with-temp-text + "* H1\n :PROPERTIES:\n :PROP: value\n :END:" + (org-export-as (org-test-default-backend) + nil nil nil '(:with-properties t))))) + (should + (equal "* H1\n:PROPERTIES:\n:B: 2\n:END:\n" + (org-test-with-temp-text + "* H1\n :PROPERTIES:\n :A: 1\n :B: 2\n:END:" + (org-export-as (org-test-default-backend) + nil nil nil '(:with-properties ("B")))))) ;; Statistics cookies. (should (equal ""