From 82c88878bcde732c59b68782d326c89c1e1467ee Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Wed, 21 Nov 2012 00:18:07 +0100 Subject: [PATCH] org-e-latex: Change tables attributes and implement matrix support * contrib/lisp/org-e-latex.el (org-e-latex-table-matrix-macros, org-e-latex-default-table-mode): New variables. (org-e-latex-tables-verbatim): Removed variable. (org-e-latex-tables-booktabs): Update docstring. (org-e-latex--align-string, org-e-latex--org-table, org-e-latex--table.el-table): Rename functions from, respectively `org-e-latex-table--align-string', `org-e-latex-table--org-table' and `org-e-latex-table--table.el-table'. Use new attributes. (org-e-latex-table,org-e-latex-table-row): Use new attributes. (org-e-latex--math-table): New function. --- contrib/lisp/org-e-latex.el | 346 ++++++++++++++++++++++++++++---------------- 1 file changed, 225 insertions(+), 121 deletions(-) diff --git a/contrib/lisp/org-e-latex.el b/contrib/lisp/org-e-latex.el index 84ef2a5b6..f385f8b2c 100644 --- a/contrib/lisp/org-e-latex.el +++ b/contrib/lisp/org-e-latex.el @@ -22,16 +22,54 @@ ;; ;; This library implements a LaTeX back-end for Org generic exporter. ;; -;; To test it, run +;; Depending on the desired output format, three commands are provided +;; for export: `org-e-latex-export-as-latex' (temporary buffer), +;; `org-e-latex-export-to-latex' ("tex" file) and +;; `org-e-latex-export-to-pdf' ("pdf" file). Also, two publishing +;; functions are available: `org-e-latex-publish-to-latex' and +;; `org-e-latex-publish-to-pdf'. ;; -;; M-: (org-export-to-buffer 'e-latex "*Test e-LaTeX*") RET +;; The library introduces three new buffer keywords: "LATEX_CLASS", +;; "LATEX_CLASS_OPTIONS" and "LATEX_HEADER". ;; -;; in an org-mode buffer then switch to the buffer to see the LaTeX -;; export. See contrib/lisp/org-export.el for more details on how -;; this exporter works. +;; Table export can be controlled with a number of attributes (through +;; ATTR_LATEX keyword). ;; -;; It introduces three new buffer keywords: "LATEX_CLASS", -;; "LATEX_CLASS_OPTIONS" and "LATEX_HEADER". +;; - The main one is the `:mode' attribute, which can be set to +;; `table', `math', `inline-math' and `verbatim'. In particular, +;; when in `math' or `inline-math' mode, every cell is exported +;; as-is and the table will be wrapped in a math environment. Also, +;; horizontal rules are ignored. These modes are particularly +;; useful to write matrices. Default mode is stored in +;; `org-e-latex-default-table-mode'. +;; +;; - The second most important attribute is `:environment'. It is the +;; environment used for the table and defaults to +;; `org-e-latex-default-table-environment' value. It can be set to +;; anything, including "tabularx", "longtable", "array", +;; "bmatrix"... +;; +;; - `:float' attribute defines a float environment for the table. +;; Possible values are `sidewaystable', `multicolumn' and `table'. +;; +;; - `:width' and `:align' attributes set, respectively, the width of +;; the table and its alignment string. +;; +;; - `:booktabs', `:center' and `:rmlines' values are booleans. They +;; toggle, respectively "booktabs" usage (assuming the package is +;; properly loaded), table centering and removal of every horizontal +;; rule but the first one (in a "table.el" table only). +;; +;; - `:math-prefix', `:math-suffix' and `:math-arguments' are string +;; which will be inserted, respectively, before the table within the +;; math environment, after the table within the math environment, +;; and between the macro name and the contents of the table. The +;; latter attribute is necessary to matrix macros that require more +;; than one argument (i.e. "qbordermatrix"). +;; +;; This back-end also offers enhanced support for footnotes. Thus, it +;; handles nested footnotes, footnotes in tables and footnotes in item +;; descriptions. ;;; Code: @@ -164,6 +202,11 @@ ("uk" . "ukrainian")) "Alist between language code and corresponding Babel option.") +(defconst org-e-latex-table-matrix-macros '(("bordermatrix" . "\\cr") + ("qbordermatrix" . "\\cr") + ("kbordermatrix" . "\\\\")) + "Alist between matrix macros and their row ending.") + ;;; User Configurable Variables @@ -436,13 +479,36 @@ default we use here encompasses both." :group 'org-export-e-latex :type 'string) -(defcustom org-e-latex-tables-centered t - "When non-nil, tables are exported in a center environment." +(defcustom org-e-latex-default-table-mode 'table + "Default mode for tables. + +Value can be a symbol among: + + `table' Regular LaTeX table. + + `math' In this mode, every cell is considered as being in math + mode and the complete table will be wrapped within a math + environment. It is particularly useful to write matrices. + + `inline-math' This mode is almost the same as `math', but the + math environment will be inlined. + + `verbatim' The table is exported as it appears in the Org + buffer, within a verbatim environment. + +This value can be overridden locally with, i.e. \":mode math\" in +LaTeX attributes. + +When modifying this variable, it may be useful to change +`org-e-latex-default-table-environment' accordingly." :group 'org-export-e-latex - :type 'boolean) + :type '(choice (const :tag "Table" table) + (const :tag "Matrix" math) + (const :tag "Inline matrix" inline-math) + (const :tag "Verbatim" verbatim))) -(defcustom org-e-latex-tables-verbatim nil - "When non-nil, tables are exported verbatim." +(defcustom org-e-latex-tables-centered t + "When non-nil, tables are exported in a center environment." :group 'org-export-e-latex :type 'boolean) @@ -450,7 +516,7 @@ default we use here encompasses both." "When non-nil, display tables in a formal \"booktabs\" style. This option assumes that the \"booktabs\" package is properly loaded in the header of the document. This value can be ignored -locally with \"booktabs=yes\" and \"booktabs=no\" LaTeX +locally with \":booktabs t\" and \":booktabs nil\" LaTeX attributes." :group 'org-export-e-latex :type 'boolean) @@ -2184,48 +2250,45 @@ contextual information." ;;;; Table ;; ;; `org-e-latex-table' is the entry point for table transcoding. It -;; takes care of tables with a "verbatim" attribute. Otherwise, it -;; delegates the job to either `org-e-latex-table--table.el-table' or -;; `org-e-latex-table--org-table' functions, depending of the type of -;; the table. +;; takes care of tables with a "verbatim" mode. Otherwise, it +;; delegates the job to either `org-e-latex--table.el-table', +;; `org-e-latex--org-table' or `org-e-latex--math-table' functions, +;; depending of the type of the table and the mode requested. ;; -;; `org-e-latex-table--align-string' is a subroutine used to build -;; alignment string for Org tables. +;; `org-e-latex--align-string' is a subroutine used to build alignment +;; string for Org tables. (defun org-e-latex-table (table contents info) "Transcode a TABLE element from Org to LaTeX. CONTENTS is the contents of the table. INFO is a plist holding contextual information." - (cond - ;; Case 1: verbatim table. - ((or org-e-latex-tables-verbatim - (let ((attr (mapconcat 'identity - (org-element-property :attr_latex table) - " "))) - (and attr (string-match "\\" attr)))) - (format "\\begin{verbatim}\n%s\n\\end{verbatim}" - ;; Re-create table, without affiliated keywords. - (org-trim - (org-element-interpret-data - `(table nil ,@(org-element-contents table)))))) - ;; Case 2: table.el table. Convert it using appropriate tools. - ((eq (org-element-property :type table) 'table.el) - (org-e-latex-table--table.el-table table contents info)) - ;; Case 3: Standard table. - (t (concat (org-e-latex-table--org-table table contents info) - ;; When there are footnote references within the table, - ;; insert they definitions just after it. - (org-e-latex--delayed-footnotes-definitions table info))))) - -(defun org-e-latex-table--align-string (table info) + (if (eq (org-element-property :type table) 'table.el) + ;; "table.el" table. Convert it using appropriate tools. + (org-e-latex--table.el-table table info) + (let ((type (or (org-export-read-attribute :attr_latex table :mode) + org-e-latex-default-table-mode))) + (cond + ;; Case 1: Verbatim table. + ((string= type "verbatim") + (format "\\begin{verbatim}\n%s\n\\end{verbatim}" + ;; Re-create table, without affiliated keywords. + (org-trim (org-element-interpret-data + `(table nil ,@(org-element-contents table)))))) + ;; Case 2: Matrix. + ((or (string= type "math") (string= type "inline-math")) + (org-e-latex--math-table table info)) + ;; Case 3: Standard table. + (t (concat (org-e-latex--org-table table contents info) + ;; When there are footnote references within the + ;; table, insert their definition just after it. + (org-e-latex--delayed-footnotes-definitions table info))))))) + +(defun org-e-latex--align-string (table info) "Return an appropriate LaTeX alignment string. TABLE is the considered table. INFO is a plist used as a communication channel." - (let ((attr (mapconcat 'identity - (org-element-property :attr_latex table) - " "))) - (if (string-match "\\" attr) "longtable") - ((string-match "\\" attr) - (org-match-string-no-properties 0 attr)) - (t org-e-latex-default-table-environment))) + (table-env (let ((env (plist-get attr :environment))) + (if env (format "%s" env) + org-e-latex-default-table-environment))) ;; If table is a float, determine environment: table, table* ;; or sidewaystable. - (float-env (cond - ((string= "longtable" table-env) nil) - ((and attr (string-match "\\" attr)) - "sidewaystable") - ((and attr - (or (string-match (regexp-quote "table*") attr) - (string-match "\\" attr))) - "table*") - ((or (not (string= caption "")) label) "table"))) + (float-env (unless (equal "longtable" table-env) + (let ((float (plist-get attr :float))) + (cond + ((string= float "sidewaystable") "sidewaystable") + ((string= float "multicolumn") "table*") + ((or (string= float "table") + (org-element-property :caption table)) + "table"))))) ;; Extract others display options. - (width (and attr (string-match "\\" attr)) - (let ((n 0) (pos 0)) - (while (and (< (length output) pos) - (setq pos (string-match "^\\\\hline\n?" output pos))) - (incf n) - (unless (= n 2) - (setq output (replace-match "" nil nil output))))))) - (if (not org-e-latex-tables-centered) output - (format "\\begin{center}\n%s\n\\end{center}" output)))) + (when (org-export-read-attribute :attr_latex table :rmlines) + (let ((n 0) (pos 0)) + (while (and (< (length output) pos) + (setq pos (string-match "^\\\\hline\n?" output pos))) + (incf n) + (unless (= n 2) (setq output (replace-match "" nil nil output)))))) + (let ((centerp (if (plist-member attr :center) (plist-get attr :center) + org-e-latex-tables-centered))) + (if (not centerp) output + (format "\\begin{center}\n%s\n\\end{center}" output))))) + +(defun org-e-latex--math-table (table info) + "Return appropriate LaTeX code for a matrix. + +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-e-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-e-latex-default-table-environment))) + (contents + (mapconcat + (lambda (row) + ;; Ignore horizontal rules. + (when (eq (org-element-property :type row) 'standard) + ;; Return each cell unmodified. + (concat + (mapconcat + (lambda (cell) + (substring (org-element-interpret-data cell) 0 -1)) + (org-element-map row 'table-cell 'identity info) "&") + (or (cdr (assoc env org-e-latex-table-matrix-macros)) "\\\\") + "\n"))) + (org-element-map table 'table-row 'identity info) ""))) + (concat + ;; Opening string. + (cond (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) "")) + ;; Environment. Also treat special cases. + (cond ((equal env "array") + (let ((align (org-e-latex--align-string table info))) + (format "\\begin{array}{%s}\n%s\\end{array}" align contents))) + ((assoc env org-e-latex-table-matrix-macros) + (format "\\%s%s{\n%s}" env + (format "%s" (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) "")) + ;; Closing string. + (cond (inlinep "\\)") + ((org-string-nw-p caption) "\\end{equation}") + (t "\\]"))))) ;;;; Table Cell @@ -2386,18 +2491,17 @@ a communication channel." ;; Rules are ignored since table separators are deduced from ;; borders of the current row. (when (eq (org-element-property :type table-row) 'standard) - (let* ((attr (mapconcat 'identity - (org-element-property - :attr_latex (org-export-get-parent table-row)) - " ")) - (longtablep (and attr (string-match "\\" attr))) - (booktabsp - (or (and attr (string-match "\\" attr)) - org-e-latex-tables-booktabs)) + (let* ((attr (org-export-read-attribute :attr_latex + (org-export-get-parent table-row))) + (longtablep (string= (or (plist-get attr :environment) + org-e-latex-default-table-environment) + "longtable")) + (booktabsp (if (plist-member attr :booktabs) + (plist-get attr :booktabs) + org-e-latex-tables-booktabs)) ;; TABLE-ROW's borders are extracted from its first cell. - (borders - (org-export-table-cell-borders - (car (org-element-contents table-row)) info))) + (borders (org-export-table-cell-borders + (car (org-element-contents table-row)) info))) (concat ;; When BOOKTABS are activated enforce top-rule even when no ;; hline was specifically marked. -- 2.11.4.GIT