From e9fd334eb4ce4253875d84c34cb9ab750794fda5 Mon Sep 17 00:00:00 2001 From: Jambunathan K Date: Tue, 17 Jan 2012 02:25:47 +0530 Subject: [PATCH] Add support for indented tables in ODT export * etc/styles/OrgOdtContentTemplate.xml (OrgIndentedSection-Level-*): New section styles. These sections are indented to the same level as the corresponding list entries. These sections hold tables that occur within a list. (OrgTable): Increased relative width from 90% to 96% for aesthetic reasons. * lisp/org-odt.el (org-odt-table-indentedp): New variable (org-odt-begin-table): Modified. If the table is within a list, temporarily leave the list and begin an indented section before emitting the table. (org-odt-end-table): Modified. If the table was within a list, close the indented section and re-open the list immediately after ending the table. (org-odt-continue-list, org-odt-discontinue-list): Helper routines to temporarily discontinue and continue a list. (org-odt-list-stack-stashed): New variable to hold the state of a pending list. (org-odt-begin-list, org-odt-begin-list-item) (org-odt-end-list-item): Modified. Handle nitty-gritties for continuing a list and list item. (org-odt-section-count): New variable that keeps track of section count. Used in conjunction with naming of sections. (org-odt-begin-section, org-odt-end-section): New defuns. (org-odt-init-outfile): Initialize `org-odt-list-stack-stashed' and `org-odt-section-count'. * lisp/org-lparse.el (org-lparse-list-item-count): Removed. Was a superfluous variable. (org-lparse-list-level): Removed. Now derived from `org-lparse-list-stack'. (org-lparse-list-stack): New. List that records the list types - ordered, unordered or descriptive - in the following order: self, parent, grand-parent etc. (org-do-lparse): Added, removed above let-bound vars. Disallowed regular tables within list-table block. (org-lparse-begin-list, org-lparse-end-list) (org-lparse-begin-list-item, org-lparse-end-list-item): Propagate above changes. OpenDocument doesn't permit tables to occur in the middle of a list. Use list continuations and indented sections to typeset indented tables. Fixes the following bug: http://lists.gnu.org/archive/html/emacs-orgmode/2012-01/msg00515.html --- etc/styles/OrgOdtContentTemplate.xml | 55 +++++++++++- lisp/org-lparse.el | 129 +++++++++++++-------------- lisp/org-odt.el | 65 ++++++++++++-- 3 files changed, 172 insertions(+), 77 deletions(-) diff --git a/etc/styles/OrgOdtContentTemplate.xml b/etc/styles/OrgOdtContentTemplate.xml index f4982f620..d981631fb 100644 --- a/etc/styles/OrgOdtContentTemplate.xml +++ b/etc/styles/OrgOdtContentTemplate.xml @@ -45,8 +45,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/lisp/org-lparse.el b/lisp/org-lparse.el index 8c98ea767..4d88ba062 100644 --- a/lisp/org-lparse.el +++ b/lisp/org-lparse.el @@ -603,11 +603,7 @@ version." (org-lparse-par-open-stashed 0) ;; list related vars - (org-lparse-list-level 0) ; list level starts at 1. A - ; value of 0 implies we are - ; outside of any list - (org-lparse-list-item-count 0) - org-lparse-list-stack + (org-lparse-list-stack '()) ;; list-table related vars org-lparse-list-table-p @@ -1086,10 +1082,11 @@ version." table-buffer (nreverse table-buffer) table-orig-buffer (nreverse table-orig-buffer)) (org-lparse-end-paragraph) + (when org-lparse-list-table-p + (error "Regular tables are not allowed in a list-table block")) (org-lparse-insert 'TABLE table-buffer table-orig-buffer))) ;; Normal lines - (t ;; This line either is list item or end a list. (when (get-text-property 0 'list-item line) @@ -2109,8 +2106,6 @@ When TITLE is nil, just close all open levels." ("d" . description))))) ;; following vars are bound during `org-do-lparse' -(defvar org-lparse-list-level) -(defvar org-lparse-list-item-count) (defvar org-lparse-list-stack) (defvar org-lparse-list-table:table-row) (defvar org-lparse-list-table:lines) @@ -2152,73 +2147,69 @@ When TITLE is nil, just close all open levels." ;; https://lists.gnu.org/archive/html/emacs-orgmode/2011-03/msg01101.html (defun org-lparse-begin-list (ltype) - (incf org-lparse-list-level) - (push org-lparse-list-item-count org-lparse-list-stack) - (setq org-lparse-list-item-count 0) - (cond - ((not org-lparse-list-table-p) - (org-lparse-begin 'LIST ltype)) - ;; process LIST-TABLE - ((= 1 org-lparse-list-level) - ;; begin LIST-TABLE - (setq org-lparse-list-table:lines nil) - (setq org-lparse-list-table:table-row nil)) - ((= 2 org-lparse-list-level) - (ignore)) - (t - (org-lparse-begin 'LIST ltype)))) + (push ltype org-lparse-list-stack) + (let ((list-level (length org-lparse-list-stack))) + (cond + ((not org-lparse-list-table-p) + (org-lparse-begin 'LIST ltype)) + ;; process LIST-TABLE + ((= 1 list-level) + ;; begin LIST-TABLE + (setq org-lparse-list-table:lines nil) + (setq org-lparse-list-table:table-row nil)) + ((= 2 list-level) + (ignore)) + (t + (org-lparse-begin 'LIST ltype))))) (defun org-lparse-end-list (ltype) - (setq org-lparse-list-item-count (pop org-lparse-list-stack)) - (decf org-lparse-list-level) - (cond - ((not org-lparse-list-table-p) - (org-lparse-end 'LIST ltype)) - ;; process LIST-TABLE - ((= 0 org-lparse-list-level) - ;; end LIST-TABLE - (insert (org-lparse-format-list-table - (nreverse org-lparse-list-table:lines)))) - ((= 1 org-lparse-list-level) - (ignore)) - (t - (org-lparse-end 'LIST ltype)))) + (pop org-lparse-list-stack) + (let ((list-level (length org-lparse-list-stack))) + (cond + ((not org-lparse-list-table-p) + (org-lparse-end 'LIST ltype)) + ;; process LIST-TABLE + ((= 0 list-level) + ;; end LIST-TABLE + (insert (org-lparse-format-list-table + (nreverse org-lparse-list-table:lines)))) + ((= 1 list-level) + (ignore)) + (t + (org-lparse-end 'LIST ltype))))) (defun org-lparse-begin-list-item (ltype &optional arg headline) - (incf org-lparse-list-item-count) - (cond - ((not org-lparse-list-table-p) - (org-lparse-begin 'LIST-ITEM ltype arg headline)) - ;; process LIST-TABLE - ((and (= 1 org-lparse-list-level) - (= 1 org-lparse-list-item-count)) - ;; begin TABLE-ROW for LIST-TABLE - (setq org-lparse-list-table:table-row nil) - (org-lparse-begin-list-table:table-cell)) - ((and (= 2 org-lparse-list-level) - (= 1 org-lparse-list-item-count)) - ;; begin TABLE-CELL for LIST-TABLE - (org-lparse-begin-list-table:table-cell)) - (t - (org-lparse-begin 'LIST-ITEM ltype arg headline)))) + (let ((list-level (length org-lparse-list-stack))) + (cond + ((not org-lparse-list-table-p) + (org-lparse-begin 'LIST-ITEM ltype arg headline)) + ;; process LIST-TABLE + ((= 1 list-level) + ;; begin TABLE-ROW for LIST-TABLE + (setq org-lparse-list-table:table-row nil) + (org-lparse-begin-list-table:table-cell)) + ((= 2 list-level) + ;; begin TABLE-CELL for LIST-TABLE + (org-lparse-begin-list-table:table-cell)) + (t + (org-lparse-begin 'LIST-ITEM ltype arg headline))))) (defun org-lparse-end-list-item (ltype) - (decf org-lparse-list-item-count) - (cond - ((not org-lparse-list-table-p) - (org-lparse-end 'LIST-ITEM ltype)) - ;; process LIST-TABLE - ((and (= 1 org-lparse-list-level) - (= 0 org-lparse-list-item-count)) - ;; end TABLE-ROW for LIST-TABLE - (org-lparse-end-list-table:table-cell) - (push (nreverse org-lparse-list-table:table-row) - org-lparse-list-table:lines)) - ((= 2 org-lparse-list-level) - ;; end TABLE-CELL for LIST-TABLE - (org-lparse-end-list-table:table-cell)) - (t - (org-lparse-end 'LIST-ITEM ltype)))) + (let ((list-level (length org-lparse-list-stack))) + (cond + ((not org-lparse-list-table-p) + (org-lparse-end 'LIST-ITEM ltype)) + ;; process LIST-TABLE + ((= 1 list-level) + ;; end TABLE-ROW for LIST-TABLE + (org-lparse-end-list-table:table-cell) + (push (nreverse org-lparse-list-table:table-row) + org-lparse-list-table:lines)) + ((= 2 list-level) + ;; end TABLE-CELL for LIST-TABLE + (org-lparse-end-list-table:table-cell)) + (t + (org-lparse-end 'LIST-ITEM ltype))))) (defvar org-lparse-list-table:table-cell-open) (defun org-lparse-begin-list-table:table-cell () diff --git a/lisp/org-odt.el b/lisp/org-odt.el index 838a327b0..7cff0462d 100644 --- a/lisp/org-odt.el +++ b/lisp/org-odt.el @@ -648,6 +648,15 @@ PUB-DIR is set, use this as the publishing directory." (defun org-odt-end-outline-text () (ignore)) +(defvar org-odt-section-count 0) +(defun org-odt-begin-section (style &optional name) + (setq name (or name (format "Section-%d" (incf org-odt-section-count)))) + (org-lparse-insert-tag + "" style name)) + +(defun org-odt-end-section () + (org-lparse-insert-tag "")) + (defun org-odt-begin-paragraph (&optional style) (org-lparse-insert-tag "" (org-odt-get-extra-attrs-for-paragraph-style style))) @@ -731,13 +740,17 @@ PUB-DIR is set, use this as the publishing directory." (list)) (t (error "Unknown environment %s" style)))) -(defvar org-lparse-list-level) ; dynamically bound in org-do-lparse +(defvar org-lparse-list-stack) ; dynamically bound in org-do-lparse +(defvar org-odt-list-stack-stashed) (defun org-odt-begin-list (ltype) (setq ltype (or (org-lparse-html-list-type-to-canonical-list-type ltype) ltype)) (let* ((style-name (org-odt-get-style-name-for-entity 'list ltype)) - (extra (concat (when (= org-lparse-list-level 1) - " text:continue-numbering=\"false\"") + (extra (concat (if (or org-lparse-list-table-p + (and (= 1 (length org-lparse-list-stack)) + (null org-odt-list-stack-stashed))) + " text:continue-numbering=\"false\"" + " text:continue-numbering=\"true\"") (when style-name (format " text:style-name=\"%s\"" style-name))))) (case ltype @@ -760,11 +773,15 @@ PUB-DIR is set, use this as the publishing directory." (ordered (assert (not headline) t) (let* ((counter arg) (extra "")) - (org-lparse-insert-tag "") + (org-lparse-insert-tag (if (= (length org-lparse-list-stack) + (length org-odt-list-stack-stashed)) + "" "")) (org-lparse-begin-paragraph))) (unordered (let* ((id arg) (extra "")) - (org-lparse-insert-tag "") + (org-lparse-insert-tag (if (= (length org-lparse-list-stack) + (length org-odt-list-stack-stashed)) + "" "")) (org-lparse-begin-paragraph) (insert (if headline (org-odt-format-target headline id) (org-odt-format-bookmark "" id))))) @@ -785,13 +802,30 @@ PUB-DIR is set, use this as the publishing directory." ltype)) (case ltype ((ordered unordered) - (org-lparse-insert-tag "")) + (org-lparse-insert-tag (if (= (length org-lparse-list-stack) + (length org-odt-list-stack-stashed)) + (prog1 "" + (setq org-odt-list-stack-stashed nil)) + ""))) (description (org-lparse-end-list-item-1) (org-lparse-end-list 'description) (org-lparse-end-list-item-1)) (t (error "Unknown list type")))) +(defun org-odt-discontinue-list () + (let ((stashed-stack org-lparse-list-stack)) + (loop for list-type in stashed-stack + do (org-lparse-end-list-item-1 list-type) + (org-lparse-end-list list-type)) + (setq org-odt-list-stack-stashed stashed-stack))) + +(defun org-odt-continue-list () + (setq org-odt-list-stack-stashed (nreverse org-odt-list-stack-stashed)) + (loop for list-type in org-odt-list-stack-stashed + do (org-lparse-begin-list list-type) + (org-lparse-begin-list-item list-type))) + ;; Following variables are let bound when table emission is in ;; progress. See org-lparse.el. (defvar org-lparse-table-begin-marker) @@ -899,7 +933,19 @@ style from the list." :key-type symbol :value-type (const :tag "True" t)))))) +(defvar org-odt-table-indentedp nil) (defun org-odt-begin-table (caption label attributes) + (setq org-odt-table-indentedp (not (null org-lparse-list-stack))) + (when org-odt-table-indentedp + ;; Within the Org file, the table is appearing within a list item. + ;; OpenDocument doesn't allow table to appear within list items. + ;; Temporarily terminate the list, emit the table and then + ;; re-continue the list. + (org-odt-discontinue-list) + ;; Put the Table in an indented section. + (let ((level (length org-odt-list-stack-stashed))) + (org-odt-begin-section (format "OrgIndentedSection-Level-%d" level)))) + (setq org-odt-table-style attributes) (setq org-odt-table-style-spec (assoc org-odt-table-style org-export-odt-table-styles)) @@ -942,7 +988,10 @@ style from the list." ((equal spec "table-cell:style-name") (replace-match table-cell-style t t)))))) (goto-char (point-max)) - (org-lparse-insert-tag "")) + (org-lparse-insert-tag "") + (when org-odt-table-indentedp + (org-odt-end-section) + (org-odt-continue-list))) (defun org-odt-begin-table-rowgroup (&optional is-header-row) (when org-lparse-table-rowgrp-open @@ -2055,7 +2104,9 @@ CATEGORY-HANDLE is used. See (setq org-odt-manifest-file-entries nil org-odt-embedded-images-count 0 org-odt-embedded-formulas-count 0 + org-odt-section-count 0 org-odt-entity-labels-alist nil + org-odt-list-stack-stashed nil org-odt-entity-counts-plist nil) content-file))