From e3a89f40f497297fd7c0ffe9273ede724684b4b9 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Sat, 9 Mar 2013 00:58:31 +0100 Subject: [PATCH 1/2] ox: Simplify syntax for attributes * lisp/ox.el (org-export-read-attribute): Do not use `read' to read attributes. Instead, extract keywords and values from it, which means each value will be a string when non-nil. * contrib/lisp/ox-groff.el (org-groff-link--inline-image): Use new attribute syntax. Small refactoring. * lisp/ox-ascii.el (org-ascii-horizontal-rule): Use new attribute syntax. * lisp/ox-beamer.el (org-beamer-plain-list): Use new attribute syntax. * lisp/ox-html.el (org-html--textarea-block): Use new attribute syntax. * lisp/ox-latex.el (org-latex--inline-image, org-latex--org-table, org-latex--math-table): Use new attribute syntax. * lisp/ox-man.el (org-man-table--org-table): Use new attribute syntax. Small refactoring. * lisp/ox-odt.el (org-odt-link--inline-image, org-odt-table-cell): Use new attribute syntax. * testing/lisp/test-ox.el: Add tests. This patch introduces two changes. To begin with, it removes the need for quoting and escaping characters. Also, all non-nil values are stored as strings. As an exception "nil" is stored as nil. --- contrib/lisp/ox-groff.el | 45 ++++++++++++++------------------------------- lisp/ox-ascii.el | 4 +++- lisp/ox-beamer.el | 6 +++--- lisp/ox-html.el | 6 +++--- lisp/ox-latex.el | 47 +++++++++++++++++++++++------------------------ lisp/ox-man.el | 30 ++++++++---------------------- lisp/ox-odt.el | 22 +++++++++++++++------- lisp/ox.el | 19 ++++++++++++++++--- testing/lisp/test-ox.el | 25 +++++++++++++++++++++++-- 9 files changed, 108 insertions(+), 96 deletions(-) diff --git a/contrib/lisp/ox-groff.el b/contrib/lisp/ox-groff.el index 96a688a..5e64023 100644 --- a/contrib/lisp/ox-groff.el +++ b/contrib/lisp/ox-groff.el @@ -1209,11 +1209,11 @@ used as a communication channel." (expand-file-name raw-path)))) (attr (org-export-read-attribute :attr_groff link)) (placement - (case (plist-get attr :position) - ('center "") - ('left "-L") - ('right "-R") - (t ""))) + (let ((pos (plist-get attr :position))) + (cond ((string= pos 'center) "") + ((string= pos 'left) "-L") + ((string= pos 'right) "-R") + (t "")))) (width (or (plist-get attr :width) "")) (height (or (plist-get attr :height) "")) (caption (and (not (plist-get attr :disable-caption)) @@ -1223,7 +1223,7 @@ used as a communication channel." (concat (cond ((and org-groff-raster-to-ps - (or (string-match ".\.png$" path) + (or (string-match ".\.png$" path) (string-match ".\.jpg$" path))) (let ((eps-path (concat path ".eps"))) (shell-command (format org-groff-raster-to-ps path eps-path)) @@ -1658,37 +1658,20 @@ This function assumes TABLE has `org' as its `:type' attribute." (lines (org-split-string contents "\n")) (attr-list - (let (result-list) - (dolist (attr-item - (list - (if (plist-get attr :expand) - "expand" nil) - - (case (plist-get attr :placement) - ('center "center") - ('left nil) - (t - (if org-groff-tables-centered - "center" ""))) - - (case (plist-get attr :boxtype) - ('box "box") - ('doublebox "doublebox") - ('allbox "allbox") - ('none nil) - (t "box")))) - - (if (not (null attr-item)) - (add-to-list 'result-list attr-item))) - result-list)) + (delq nil + (list (and (plist-get attr :expand) "expand") + (let ((placement (plist-get attr :placement))) + (cond ((string= placement 'center) "center") + ((string= placement 'left) nil) + (t (if org-groff-tables-centered "center" "")))) + (or (plist-get attr :boxtype) "box")))) (title-line (plist-get attr :title-line)) (long-cells (plist-get attr :long-cells)) (table-format (concat - (format "%s" - (or (car attr-list) "")) + (or (car attr-list) "") (or (let (output-list) (when (cdr attr-list) diff --git a/lisp/ox-ascii.el b/lisp/ox-ascii.el index 76da33a..6eb96b3 100644 --- a/lisp/ox-ascii.el +++ b/lisp/ox-ascii.el @@ -1218,7 +1218,9 @@ information." (spec-width (org-export-read-attribute :attr_ascii horizontal-rule :width))) (org-ascii--justify-string - (make-string (if (wholenump spec-width) spec-width text-width) + (make-string (if (and spec-width (string-match "^[0-9]+$" spec-width)) + (string-to-number spec-width) + text-width) (if (eq (plist-get info :ascii-charset) 'utf-8) ?― ?-)) text-width 'center))) diff --git a/lisp/ox-beamer.el b/lisp/ox-beamer.el index 282da7c..f0f5ef0 100644 --- a/lisp/ox-beamer.el +++ b/lisp/ox-beamer.el @@ -783,7 +783,7 @@ contextual information." (org-export-read-attribute :attr_latex plain-list) (org-export-read-attribute :attr_beamer plain-list))) (latex-type (let ((env (plist-get attributes :environment))) - (cond (env (format "%s" env)) + (cond (env) ((eq type 'ordered) "enumerate") ((eq type 'descriptive) "description") (t "itemize"))))) @@ -793,11 +793,11 @@ contextual information." latex-type ;; Default overlay specification, if any. (org-beamer--normalize-argument - (format "%s" (or (plist-get attributes :overlay) "")) + (or (plist-get attributes :overlay) "") 'defaction) ;; Second optional argument depends on the list type. (org-beamer--normalize-argument - (format "%s" (or (plist-get attributes :options) "")) + (or (plist-get attributes :options) "") 'option) ;; Eventually insert contents and close environment. contents diff --git a/lisp/ox-html.el b/lisp/ox-html.el index 829fe28..8c3a993 100644 --- a/lisp/ox-html.el +++ b/lisp/ox-html.el @@ -1214,9 +1214,9 @@ When STANDALONE-P is t, wrap the into a
...
." (defun org-html--textarea-block (element) "Transcode ELEMENT into a textarea block. ELEMENT is either a src block or an example block." - (let ((code (car (org-export-unravel-code element))) - (attr (org-export-read-attribute :attr_html element))) - (format "

\n\n

" + (let* ((code (car (org-export-unravel-code element))) + (attr (org-export-read-attribute :attr_html element))) + (format "

\n\n

" (or (plist-get attr :width) 80) (or (plist-get attr :height) (org-count-lines code)) code))) diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index 3d3fc3a..fa66bb4 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -1814,17 +1814,17 @@ used as a communication channel." (comment-include (if (plist-get attr :comment-include) "%" "")) ;; It is possible to specify width and height in the ;; ATTR_LATEX line, and also via default variables. - (width (format "%s" (cond ((plist-get attr :width)) - ((plist-get attr :height) "") - ((eq float 'figure) "0.7\\textwidth") - ((eq float 'wrap) "0.48\\textwidth") - (t org-latex-image-default-width)))) - (height (format "%s" (cond ((plist-get attr :height)) - ((or (plist-get attr :width) - (memq float '(figure wrap))) "") - (t org-latex-image-default-height)))) - (options (let ((opt (format "%s" (or (plist-get attr :options) - org-latex-image-default-option)))) + (width (cond ((plist-get attr :width)) + ((plist-get attr :height) "") + ((eq float 'figure) "0.7\\textwidth") + ((eq float 'wrap) "0.48\\textwidth") + (t org-latex-image-default-width))) + (height (cond ((plist-get attr :height)) + ((or (plist-get attr :width) + (memq float '(figure wrap))) "") + (t org-latex-image-default-height))) + (options (let ((opt (or (plist-get attr :options) + org-latex-image-default-option))) (if (not (string-match "\\`\\[\\(.*\\)\\]\\'" opt)) opt (match-string 1 opt)))) image-code) @@ -2421,9 +2421,8 @@ This function assumes TABLE has `org' as its `:type' property and ;; Determine alignment string. (alignment (org-latex--align-string table info)) ;; Determine environment for the table: longtable, tabular... - (table-env (let ((env (plist-get attr :environment))) - (if env (format "%s" env) - org-latex-default-table-environment))) + (table-env (or (plist-get attr :environment) + org-latex-default-table-environment)) ;; If table is a float, determine environment: table, table* ;; or sidewaystable. (float-env (unless (equal "longtable" table-env) @@ -2436,7 +2435,7 @@ This function assumes TABLE has `org' as its `:type' property and "table"))))) ;; Extract others display options. (fontsize (let ((font (plist-get attr :font))) - (and font (concat (org-trim (format "%s" font)) "\n")))) + (and font (concat font "\n")))) (width (plist-get attr :width)) (placement (or (plist-get attr :placement) (format "[%s]" org-latex-default-figure-position))) @@ -2527,9 +2526,8 @@ This function assumes TABLE has `org' as its `:type' property and (let* ((caption (org-latex--caption/label-string table info)) (attr (org-export-read-attribute :attr_latex table)) (inlinep (eq (plist-get attr :mode) 'inline-math)) - (env (let ((env (plist-get attr :environment))) - (if env (format "%s" env) - org-latex-default-table-environment))) + (env (or (plist-get attr :environment) + org-latex-default-table-environment)) (contents (mapconcat (lambda (row) @@ -2566,19 +2564,20 @@ This function assumes TABLE has `org' as its `:type' property and (inlinep "\\(") ((org-string-nw-p caption) (concat "\\begin{equation}\n" caption)) (t "\\[")) - ;; Prefix (make sure it is a string). - (format "%s" (or (plist-get attr :math-prefix) "")) + ;; Prefix. + (or (plist-get attr :math-prefix) "") ;; Environment. Also treat special cases. (cond ((equal env "array") (let ((align (org-latex--align-string table info))) (format "\\begin{array}{%s}\n%s\\end{array}" align contents))) ((assoc env org-latex-table-matrix-macros) - (format "\\%s%s{\n%s}" env - (format "%s" (or (plist-get attr :math-arguments) "")) + (format "\\%s%s{\n%s}" + env + (or (plist-get attr :math-arguments) "") contents)) (t (format "\\begin{%s}\n%s\\end{%s}" env contents env))) - ;; Suffix (make sure it is a string). - (format "%s" (or (plist-get attr :math-suffix) "")) + ;; Suffix. + (or (plist-get attr :math-suffix) "") ;; Closing string. If TABLE is in the middle of a table cluster, ;; do not insert any. If it closes such a cluster, be sure to ;; close the cluster with a string matching the opening string. diff --git a/lisp/ox-man.el b/lisp/ox-man.el index 4c17e49..7fc7f02 100644 --- a/lisp/ox-man.el +++ b/lisp/ox-man.el @@ -945,28 +945,14 @@ This function assumes TABLE has `org' as its `:type' attribute." (lines (org-split-string contents "\n")) (attr-list - (let ((result-list '())) - (dolist (attr-item - (list - (if (plist-get attr :expand) - "expand" nil) - - (case (plist-get attr :placement) - ('center "center") - ('left nil) - (t (if org-man-tables-centered "center" ""))) - - (case (plist-get attr :boxtype) - ('box "box") - ('doublebox "doublebox") - ('allbox "allbox") - ('none nil) - (t "box")))) - - (if attr-item - (add-to-list 'result-list attr-item))) - result-list )) - + (delq nil + (list + (and (plist-get attr :expand) "expand") + (let ((placement (plist-get attr :placement))) + (cond ((string= placement 'center) "center") + ((string= placement 'left) nil) + (t (if org-man-tables-centered "center" "")))) + (or (plist-get attr :boxtype) "box")))) (title-line (plist-get attr :title-line)) (long-cells (plist-get attr :long-cells)) diff --git a/lisp/ox-odt.el b/lisp/ox-odt.el index a1caff7..d9dd525 100644 --- a/lisp/ox-odt.el +++ b/lisp/ox-odt.el @@ -2341,12 +2341,19 @@ used as a communication channel." (list user-frame-style user-frame-attrs user-frame-anchor)) ;; (embed-as (or embed-as user-frame-anchor "paragraph")) ;; extrac - ;; handle `:width', `:height' and `:scale' properties. + ;; + ;; Handle `:width', `:height' and `:scale' properties. Read + ;; them as numbers since we need them for computations. (size (org-odt--image-size - src-expanded (plist-get attr-plist :width) - (plist-get attr-plist :height) - (plist-get attr-plist :scale) nil ;; embed-as - "paragraph" ; FIXME + src-expanded + (let ((width (plist-get attr-plist :width))) + (and width (read width))) + (let ((length (plist-get attr-plist :length))) + (and length (read length))) + (let ((scale (plist-get attr-plist :scale))) + (and scale (read scale))) + nil ; embed-as + "paragraph" ; FIXME )) (width (car size)) (height (cdr size)) (standalone-link-p (org-odt--standalone-link-p element info)) @@ -3351,8 +3358,9 @@ channel." "OrgTableHeading") ((let* ((table (org-export-get-parent-table table-cell)) (table-attrs (org-export-read-attribute :attr_odt table)) - (table-header-columns (plist-get table-attrs - :header-columns))) + (table-header-columns + (let ((cols (plist-get table-attrs :header-columns))) + (and cols (read cols))))) (<= c (cond ((wholenump table-header-columns) (- table-header-columns 1)) (table-header-columns 0) diff --git a/lisp/ox.el b/lisp/ox.el index 40c0617..92be8f7 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -3257,11 +3257,24 @@ that property within attributes. This function assumes attributes are defined as \":keyword value\" pairs. It is appropriate for `:attr_html' like -properties." +properties. All values will become strings except the empty +string and \"nil\", which will become nil." (let ((attributes (let ((value (org-element-property attribute element))) - (and value - (read (format "(%s)" (mapconcat 'identity value " "))))))) + (when value + (let ((s (mapconcat 'identity value " ")) result) + (while (string-match + "\\(?:^\\|[ \t]+\\)\\(:[-a-zA-Z0-9_]+\\)\\([ \t]+\\|$\\)" + s) + (let ((value (substring s 0 (match-beginning 0)))) + (push (and (not (member value '("nil" ""))) value) result)) + (push (intern (match-string 1 s)) result) + (setq s (substring s (match-end 0)))) + ;; Ignore any string before the first property with `cdr'. + (cdr (nreverse (cons (and (org-string-nw-p s) + (not (equal s "nil")) + s) + result)))))))) (if property (plist-get attributes property) attributes))) (defun org-export-get-caption (element &optional shortp) diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el index 6fa1f25..754c657 100644 --- a/testing/lisp/test-ox.el +++ b/testing/lisp/test-ox.el @@ -645,12 +645,33 @@ body\n"))) :attr_html (org-test-with-temp-text "#+ATTR_HTML: :a 1 :b 2\nParagraph" (org-element-at-point))) - '(:a 1 :b 2))) + '(:a "1" :b "2"))) ;; Return nil on empty attribute. (should-not (org-export-read-attribute :attr_html - (org-test-with-temp-text "Paragraph" (org-element-at-point))))) + (org-test-with-temp-text "Paragraph" (org-element-at-point)))) + ;; Return nil on "nil" string. + (should + (equal '(:a nil :b nil) + (org-export-read-attribute + :attr_html + (org-test-with-temp-text "#+ATTR_HTML: :a nil :b nil\nParagraph" + (org-element-at-point))))) + ;; Return nil on empty string. + (should + (equal '(:a nil :b nil) + (org-export-read-attribute + :attr_html + (org-test-with-temp-text "#+ATTR_HTML: :a :b\nParagraph" + (org-element-at-point))))) + ;; Ignore text before first property. + (should-not + (member "ignore" + (org-export-read-attribute + :attr_html + (org-test-with-temp-text "#+ATTR_HTML: ignore :a 1\nParagraph" + (org-element-at-point)))))) (ert-deftest test-org-export/get-caption () "Test `org-export-get-caption' specifications." -- 1.8.1.5