summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <n.goaziou@gmail.com>2012-11-21 00:18:07 +0100
committerNicolas Goaziou <n.goaziou@gmail.com>2012-11-21 17:28:03 +0100
commit82c88878bcde732c59b68782d326c89c1e1467ee (patch)
tree6d3d9dde316d181482122972f7bb98fa658d37a9
parentd939c4fb755afcc4ef3a50784d108917e2d906ae (diff)
downloadorg-mode-82c88878bcde732c59b68782d326c89c1e1467ee.tar.gz
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.
-rw-r--r--contrib/lisp/org-e-latex.el346
1 files changed, 225 insertions, 121 deletions
diff --git a/contrib/lisp/org-e-latex.el b/contrib/lisp/org-e-latex.el
index 84ef2a5..f385f8b 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 "\\<verbatim\\>" 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 "\\<align=\\(\\S-+\\)" attr) (match-string 1 attr)
- (let (alignment)
+ (or (org-export-read-attribute :attr_latex table :align)
+ (let (align)
;; Extract column groups and alignment from first (non-rule)
;; row.
(org-element-map
@@ -2238,96 +2301,89 @@ a communication channel."
(lambda (cell)
(let ((borders (org-export-table-cell-borders cell info)))
;; Check left border for the first cell only.
- (when (and (memq 'left borders) (not alignment))
- (push "|" alignment))
+ (when (and (memq 'left borders) (not align))
+ (push "|" align))
(push (case (org-export-table-cell-alignment cell info)
(left "l")
(right "r")
(center "c"))
- alignment)
- (when (memq 'right borders) (push "|" alignment))))
+ align)
+ (when (memq 'right borders) (push "|" align))))
info)
- (apply 'concat (reverse alignment))))))
+ (apply 'concat (nreverse align)))))
-(defun org-e-latex-table--org-table (table contents info)
+(defun org-e-latex--org-table (table contents info)
"Return appropriate LaTeX code for an Org table.
TABLE is the table type element to transcode. CONTENTS is its
contents, as a string. INFO is a plist used as a communication
channel.
-This function assumes TABLE has `org' as its `:type' attribute."
- (let* ((label (org-element-property :name table))
- (caption (org-e-latex--caption/label-string table info))
- (attr (mapconcat 'identity
- (org-element-property :attr_latex table)
- " "))
+This function assumes TABLE has `org' as its `:type' property and
+`table' as its `:mode' attribute."
+ (let* ((caption (org-e-latex--caption/label-string table info))
+ (attr (org-export-read-attribute :attr_latex table))
;; Determine alignment string.
- (alignment (org-e-latex-table--align-string table info))
+ (alignment (org-e-latex--align-string table info))
;; Determine environment for the table: longtable, tabular...
- (table-env (cond
- ((not attr) org-e-latex-default-table-environment)
- ((string-match "\\<longtable\\>" attr) "longtable")
- ((string-match "\\<tabular.?\\>" 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 "\\<sidewaystable\\>" attr))
- "sidewaystable")
- ((and attr
- (or (string-match (regexp-quote "table*") attr)
- (string-match "\\<multicolumn\\>" 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 "\\<width=\\(\\S-+\\)" attr)
- (org-match-string-no-properties 1 attr)))
- (placement
- (if (and attr (string-match "\\<placement=\\(\\S-+\\)" attr))
- (org-match-string-no-properties 1 attr)
- (format "[%s]" org-e-latex-default-figure-position))))
+ (width (plist-get attr :width))
+ (placement (or (plist-get attr :placement)
+ (format "[%s]" org-e-latex-default-figure-position)))
+ (centerp (if (plist-member attr :center) (plist-get attr :center)
+ org-e-latex-tables-centered)))
;; Prepare the final format string for the table.
(cond
;; Longtable.
- ((string= "longtable" table-env)
+ ((equal "longtable" table-env)
(format
"\\begin{longtable}{%s}\n%s%s%s\\end{longtable}"
alignment
(if (or (not org-e-latex-table-caption-above) (string= "" caption)) ""
- (concat (org-trim caption) "\\\\\n"))
+ (concat caption "\\\\\n"))
contents
(if (or org-e-latex-table-caption-above (string= "" caption)) ""
- (concat (org-trim caption) "\\\\\n"))))
+ (concat caption "\\\\\n"))))
;; Others.
- (t (concat (if float-env
- (concat
- (format "\\begin{%s}%s\n" float-env placement)
- (if org-e-latex-table-caption-above caption "")
- (when org-e-latex-tables-centered "\\centering\n"))
- (when org-e-latex-tables-centered "\\begin{center}\n"))
+ (t (concat (cond
+ (float-env
+ (concat (format "\\begin{%s}%s\n" float-env placement)
+ (if org-e-latex-table-caption-above caption "")
+ (when centerp "\\centering\n")))
+ (centerp "\\begin{center}\n"))
(format "\\begin{%s}%s{%s}\n%s\\end{%s}"
table-env
(if width (format "{%s}" width) "")
alignment
contents
table-env)
- (if float-env
- (concat (if org-e-latex-table-caption-above "" caption)
- (format "\n\\end{%s}" float-env))
- (when org-e-latex-tables-centered "\n\\end{center}")))))))
+ (cond
+ (float-env
+ (concat (if org-e-latex-table-caption-above "" caption)
+ (format "\n\\end{%s}" float-env)))
+ (centerp "\n\\end{center}")))))))
-(defun org-e-latex-table--table.el-table (table contents info)
+(defun org-e-latex--table.el-table (table info)
"Return appropriate LaTeX code for a table.el table.
-TABLE is the table type element to transcode. CONTENTS is its
-contents, as a string. INFO is a plist used as a communication
-channel.
+TABLE is the table type element to transcode. INFO is a plist
+used as a communication channel.
This function assumes TABLE has `table.el' as its `:type'
-attribute."
+property."
(require 'table)
;; Ensure "*org-export-table*" buffer is empty.
(with-current-buffer (get-buffer-create "*org-export-table*")
@@ -2345,18 +2401,67 @@ attribute."
(setq output (replace-match "" t t output)))
;; When the "rmlines" attribute is provided, remove all hlines but
;; the the one separating heading from the table body.
- (let ((attr (mapconcat 'identity
- (org-element-property :attr_latex table)
- " ")))
- (when (and attr (string-match "\\<rmlines\\>" 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 "\\<longtable\\>" attr)))
- (booktabsp
- (or (and attr (string-match "\\<booktabs=\\(yes\\|t\\)\\>" 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.