emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[O] [RFC] Simplify attributes syntax


From: Nicolas Goaziou
Subject: [O] [RFC] Simplify attributes syntax
Date: Sat, 09 Mar 2013 01:18:19 +0100

Hello,

The following patch simplifies syntax for attributes.

>From the user POV, it removes necessity to quote or escape characters.
For example, these are now valid:

  #+attr_latex: :font \footnotesize :align |l|c|c|
  #+attr_foo: :prop var="value" :another-prop nil

>From the developer POV, each non-nil value is now read as a string by
`org-export-read-attribute'.  So:

  #+attr_something: :width 70

will be read as:

  '(:width "70")

If there's no major problem with it, I'll apply it before Monday.
Though, I think ox-odt needs double-checking.


Regards,

-- 
Nicolas Goaziou
>From e3a89f40f497297fd7c0ffe9273ede724684b4b9 Mon Sep 17 00:00:00 2001
From: Nicolas Goaziou <address@hidden>
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 <img.../> into a 
<div>...</div>."
 (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 "<p>\n<textarea cols=\"%d\" rows=\"%d\">\n%s</textarea>\n</p>"
+  (let* ((code (car (org-export-unravel-code element)))
+        (attr (org-export-read-attribute :attr_html element)))
+    (format "<p>\n<textarea cols=\"%s\" rows=\"%s\">\n%s</textarea>\n</p>"
            (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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]