emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Mario Frasca <mario@anche.no>
To: emacs-orgmode@gnu.org
Subject: [PATCH] allow for multiline headers
Date: Fri, 12 Jun 2020 12:14:17 -0500	[thread overview]
Message-ID: <d9f86ea0-0ee6-0ff0-219a-e0dbc27e1896@anche.no> (raw)

[-- Attachment #1: Type: text/plain, Size: 1315 bytes --]

it misses unit tests, I need to make the collapse optional, and I need 
to hear from users what they think of it.  this patch allows me to write 
a table like the following, having a three-lines header:

|  n | data | prove, |  casi, | ratio |   prove, |    casi, |
|    |      | valore | valore |       |    media | media |
|    |      | diario | diario |       | corrente | corrente |

and this is seen as a single header line.

|  n | data | prove, valore diario | casi, valore diario | ratio | 
prove, media corrente | casi, media corrente |

I find it helpful, because this way my columns stay narrower.

as it is, ¡it fails on headerless tables!

I have not yet clear what's the best approach to handling headerless 
tables, was thinking of a org-table-max-collapse-header variable, which 
you would set to the number of lines which you are maximally expecting 
to collapse into the leading header line.  Or maybe an extra option to 
org-plot, where you would state if headers need be collapsed.

or we already had ways to achieve this same thing, and I missed them all?

best regards,


[-- Attachment #2: 0001-lisp-org-table.el-Allow-collapsing-header-into-singl.patch --]
[-- Type: text/x-patch, Size: 4565 bytes --]

From 649f46a591474afb6cef8b9d5151ff6b0bae38aa Mon Sep 17 00:00:00 2001
From: mfrasca <mario@anche.no>
Date: Fri, 12 Jun 2020 11:42:34 -0500
Subject: [PATCH] lisp/org-table.el: Allow collapsing header into single line

* lisp/org-table.el (org-table-collapse-header): new function
that collapses multiple header lines into one list.
(org-table-to-lisp): simplify code, changing a `while' to a
`cl-loop', remove leading `hline' symbols from result, edit
documentation to reflect change.

* lisp/org-plot.el (org-plot/gnuplot): use
org-table-collapse-header and trust there's no leading `hline'
symbols in lisp table.
 lisp/org-plot.el  |  6 ++---
 lisp/org-table.el | 59 ++++++++++++++++++++++++++++++++---------------
 2 files changed, 43 insertions(+), 22 deletions(-)

diff --git a/lisp/org-plot.el b/lisp/org-plot.el
index a23195d2a..662d38e54 100644
--- a/lisp/org-plot.el
+++ b/lisp/org-plot.el
@@ -289,11 +289,9 @@ line directly before or after the table."
 	(setf params (plist-put params (car pair) (cdr pair)))))
     ;; collect table and table information
     (let* ((data-file (make-temp-file "org-plot"))
-	   (table (org-table-to-lisp))
-	   (num-cols (length (if (eq (nth 0 table) 'hline) (nth 1 table)
-			       (nth 0 table)))))
+	   (table (org-table-collapse-header (org-table-to-lisp)))
+	   (num-cols (length (nth 0 table))))
       (run-with-idle-timer 0.1 nil #'delete-file data-file)
-      (while (eq 'hline (car table)) (setf table (cdr table)))
       (when (eq (cadr table) 'hline)
 	(setf params
 	      (plist-put params :labels (nth 0 table))) ; headers to labels
diff --git a/lisp/org-table.el b/lisp/org-table.el
index 6462b99c4..6549e178a 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -5433,30 +5433,53 @@ a radio table."
 (defun org-table-to-lisp (&optional txt)
   "Convert the table at point to a Lisp structure.
-The structure will be a list.  Each item is either the symbol `hline'
-for a horizontal separator line, or a list of field values as strings.
-The table is taken from the parameter TXT, or from the buffer at point."
+The returned structure is a list, where each item is either the
+symbol `hline', for a horizontal separator line, or a list of
+field values as strings.  The table is taken from the parameter
+TXT, or from the buffer at point.  Leading `hline' symbols are
+trimmed, so the first item in the result is a list"
   (if txt
         (insert txt)
-        (goto-char (point-min))
       (goto-char (org-table-begin))
-      (let ((table nil))
-        (while (re-search-forward "\\=[ \t]*|" nil t)
-	  (let ((row nil))
-	    (if (looking-at "-")
-		(push 'hline table)
-	      (while (not (progn (skip-chars-forward " \t") (eolp)))
-		(push (buffer-substring
-		       (point)
-		       (progn (re-search-forward "[ \t]*\\(|\\|$\\)")
-			      (match-beginning 0)))
-		      row))
-	      (push (nreverse row) table)))
-	  (forward-line))
-        (nreverse table)))))
+      (let ((table (cl-loop
+		    until (not (re-search-forward "\\=[ \t]*|" nil t))
+		    collect (if (looking-at "-")
+				'hline
+			      (cl-loop
+                               do (skip-chars-forward " \t")
+		               collect (buffer-substring
+					(point)
+					(progn (re-search-forward "[ \t]*\\(|\\|$\\)")
+			                       (match-beginning 0)))
+                               until (looking-at "$")))
+		    do (forward-line))))
+	(while (equal 'hline (car table))
+          (setq table (cdr table)))
+	table))))
+(defun org-table-collapse-header (table &optional glue)
+  "Collapse the lines before 'hline into a single header.
+The given TABLE is a list of lists as returned by `org-table-to-lisp'.
+The leading lines before the first `hline' symbol are considered
+forming the table header.  This function collapses all leading header
+lines into a single header line, followed by the `hline' symbol, and
+the rest of the TABLE.  Header cells are GLUEd together with a space,
+or the given character."
+  (setq glue (or glue " "))
+  (let* ((header (cl-loop for i in table
+                          until (equal i 'hline)
+                          collect i))
+         (position (length header)))
+    (cons (apply #'cl-mapcar
+		 #'(lambda (&rest x)
+		     (string-trim
+		      (mapconcat #'identity x glue)))
+		 header)
+          (nthcdr position table))))
 (defun orgtbl-send-table (&optional maybe)
   "Send a transformed version of table at point to the receiver position.

             reply	other threads:[~2020-06-12 17:23 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-12 17:14 Mario Frasca [this message]
2020-06-12 22:44 ` [PATCH] allow for multiline headers Nicolas Goaziou
2020-06-13 20:20   ` Mario Frasca
2020-06-13 21:20     ` Mario Frasca
2020-06-13 22:18     ` Nicolas Goaziou
2020-06-13 23:03       ` Mario Frasca
2020-06-14 19:23         ` Nicolas Goaziou
     [not found]           ` <3e6ee551-4ef7-7d96-93dc-19a4973e1af8@anche.no>
     [not found]             ` <871rm5vslh.fsf@nicolasgoaziou.fr>
2020-06-27 15:39               ` Mario Frasca
2020-06-28 23:17                 ` Nicolas Goaziou
2020-06-29  0:27                   ` Mario Frasca
2020-06-29 12:50                     ` Nicolas Goaziou
2020-06-29 16:26                       ` Mario Frasca
2020-06-29 18:36                         ` Nicolas Goaziou
2020-06-29 22:01                           ` Mario Frasca
2020-07-01 10:46                             ` Nicolas Goaziou
2020-07-01 12:06                               ` Mario Frasca
2020-07-04  8:58                                 ` Nicolas Goaziou
2020-07-04 13:47                                   ` Mario Frasca

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d9f86ea0-0ee6-0ff0-219a-e0dbc27e1896@anche.no \
    --to=mario@anche.no \
    --cc=emacs-orgmode@gnu.org \


* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).