From 33719e2ef930224878ace4c290b3f21707c6ca3c Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Fri, 17 Oct 2014 17:16:28 +0200 Subject: [PATCH] ox-latex: Refactor matrices code * lisp/ox-latex.el (latex): Introduce a dedicated pseudo-element: `latex-matrices'. (org-latex--wrap-latex-matrices, org-latex-matrices, org-latex-matrices-tree-filter): New functions. (org-latex--math-table): Delegate environment wrapping to new pseudo-element translator. --- lisp/ox-latex.el | 124 +++++++++++++++++++++++++++-------------------- 1 file changed, 71 insertions(+), 53 deletions(-) diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index ee48d1936..8158eb856 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -89,8 +89,9 @@ (underline . org-latex-underline) (verbatim . org-latex-verbatim) (verse-block . org-latex-verse-block) - ;; Pseudo objects. - (latex-math-block . org-latex-math-block)) + ;; Pseudo objects and elements. + (latex-math-block . org-latex-math-block) + (latex-matrices . org-latex-matrices)) :export-block '("LATEX" "TEX") :menu-entry '(?l "Export to LaTeX" @@ -102,7 +103,8 @@ (if a (org-latex-export-to-pdf t s v b) (org-open-file (org-latex-export-to-pdf nil s v b))))))) :filters-alist '((:filter-options . org-latex-math-block-options-filter) - (:filter-parse-tree . org-latex-math-block-tree-filter)) + (:filter-parse-tree org-latex-math-block-tree-filter + org-latex-matrices-tree-filter)) :options-alist '((:latex-class "LATEX_CLASS" nil org-latex-default-class t) (:latex-class-options "LATEX_CLASS_OPTIONS" nil nil t) @@ -2129,6 +2131,66 @@ holding contextual information." (format "\\begin{verbatim}\n%s\\end{verbatim}" contents))) +;;;; Pseudo Element: LaTeX Matrix + +(defun org-latex--wrap-latex-matrices (data info) + "Merge contiguous tables with the same mode within a pseudo-element. +DATA is a parse tree or a secondary string. INFO is a plist +containing export options. Modify DATA by side-effect and return +it." + (org-element-map data 'table + (lambda (table) + (when (eq (org-element-property :type table) 'org) + (let ((mode (or (org-export-read-attribute :attr_latex table :mode) + (plist-get info :latex-default-table-mode)))) + (when (and (member mode '("inline-math" "math")) + ;; Do not wrap twice the same table. + (not (eq (org-element-type + (org-element-property :parent table)) + 'latex-matrices))) + (let* ((caption (and (not (string= mode "inline-math")) + (org-element-property :caption table))) + (matrices + (list 'latex-matrices + (list :caption caption + :markup + (cond ((string= mode "inline-math") 'inline) + (caption 'equation) + (t 'math))))) + (previous table) + (next (org-export-get-next-element table info))) + (org-element-insert-before matrices table) + ;; Swallow all contiguous tables sharing the same mode. + (while (and + (zerop (or (org-element-property :post-blank previous) 0)) + (setq next (org-export-get-next-element previous info)) + (string= (or (org-export-read-attribute + :attr_latex next :mode) + (plist-get info :latex-default-table-mode)) + mode)) + (org-element-extract-element previous) + (org-element-adopt-elements matrices previous) + (setq previous next)) + (org-element-put-property + matrices :post-blank (org-element-property :post-blank previous)) + (org-element-extract-element previous) + (org-element-adopt-elements matrices previous)))))) + info) + data) + +(defun org-latex-matrices (matrices contents info) + "Transcode a MATRICES element from Org to LaTeX. +CONTENTS is a string. INFO is a plist used as a communication +channel." + (format (case (org-element-property :markup matrices) + (inline "\\(%s\\)") + (equation "\\begin{equation}\n%s\\end{equation}") + (t "\\[\n%s\\]")) + contents)) + +(defun org-latex-matrices-tree-filter (tree backend info) + (org-latex--wrap-latex-matrices tree info)) + ;;;; Pseudo Object: LaTeX Math Block (defun org-latex--wrap-latex-math-block (data info) @@ -2689,10 +2751,8 @@ TABLE is the table type element to transcode. INFO is a plist used as a communication channel. This function assumes TABLE has `org' as its `:type' property and -`inline-math' or `math' as its `:mode' attribute.." - (let* ((caption (org-latex--caption/label-string table info)) - (attr (org-export-read-attribute :attr_latex table)) - (inlinep (equal (plist-get attr :mode) "inline-math")) +`inline-math' or `math' as its `:mode' attribute." + (let* ((attr (org-export-read-attribute :attr_latex table)) (env (or (plist-get attr :environment) (plist-get info :latex-default-table-environment))) (contents @@ -2707,34 +2767,13 @@ This function assumes TABLE has `org' as its `:type' property and (substring (org-element-interpret-data cell org-latex-pseudo-objects) 0 -1)) - (org-element-map row 'table-cell 'identity info) "&") + (org-element-map row 'table-cell #'identity info) "&") (or (cdr (assoc env org-latex-table-matrix-macros)) "\\\\") "\n"))) - (org-element-map table 'table-row 'identity info) "")) - ;; Variables related to math clusters (contiguous math tables - ;; of the same type). - (mode (org-export-read-attribute :attr_latex table :mode)) - (prev (org-export-get-previous-element table info)) - (next (org-export-get-next-element table info)) - (same-mode-p - (lambda (table) - ;; Non-nil when TABLE has the same mode as current table. - (string= (or (org-export-read-attribute :attr_latex table :mode) - (plist-get info :latex-default-table-mode)) - mode)))) + (org-element-map table 'table-row #'identity info) ""))) (concat - ;; Opening string. If TABLE is in the middle of a table cluster, - ;; do not insert any. - (cond ((and prev - (eq (org-element-type prev) 'table) - (memq (org-element-property :post-blank prev) '(0 nil)) - (funcall same-mode-p prev)) - nil) - (inlinep "\\(") - ((org-string-nw-p caption) (concat "\\begin{equation}\n" caption)) - (t "\\[")) ;; Prefix. - (or (plist-get attr :math-prefix) "") + (plist-get attr :math-prefix) ;; Environment. Also treat special cases. (cond ((equal env "array") (let ((align (org-latex--align-string table info))) @@ -2746,28 +2785,7 @@ This function assumes TABLE has `org' as its `:type' property and contents)) (t (format "\\begin{%s}\n%s\\end{%s}" env contents env))) ;; 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. - (cond ((and next - (eq (org-element-type next) 'table) - (memq (org-element-property :post-blank table) '(0 nil)) - (funcall same-mode-p next)) - nil) - (inlinep "\\)") - ;; Find cluster beginning to know which environment to use. - ((let ((cluster-beg table) prev) - (while (and (setq prev (org-export-get-previous-element - cluster-beg info)) - (memq (org-element-property :post-blank prev) - '(0 nil)) - (funcall same-mode-p prev)) - (setq cluster-beg prev)) - (and (or (org-element-property :caption cluster-beg) - (org-element-property :name cluster-beg)) - "\n\\end{equation}"))) - (t "\\]"))))) + (plist-get attr :math-suffix)))) ;;;; Table Cell