emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* [PATCH] Support multiple destinations for each radio table.
  2008-02-29 10:09 ` Carsten Dominik
@ 2008-03-03  1:46   ` Jason Riedy
  0 siblings, 0 replies; 2+ messages in thread
From: Jason Riedy @ 2008-03-03  1:46 UTC (permalink / raw)
  To: Carsten Dominik; +Cc: emacs-orgmode

You can slice a single table full of calculations in different ways
into separate destinations.  Or you can format the table differently.
There are many fun and exciting possible uses.

Signed-off-by: Jason Riedy <jason@acm.org>
---
   > I think the easiest would be to write a little lisp program that
   > switches the SEND lines above the table through a number of states
   > and then calls the exporter.

   Tricking out the exporter was surprisingly simple once I thought
   about it...

 org.el   |  127 ++++++++++++++++++++++++++++++++++++--------------------------
 org.texi |    6 ++-
 2 files changed, 78 insertions(+), 55 deletions(-)

diff --git a/org.el b/org.el
index 4e27ecc..6d52fdf 100644
--- a/org.el
+++ b/org.el
@@ -11660,6 +11660,41 @@ overwritten, and the table is not marked as requiring realignment."
 	  (push (> (/ (apply '+ (mapcar (lambda (x) (if (string-match org-table-number-regexp x) 1 0)) column)) maxcol) org-table-number-fraction) org-table-last-alignment))
     (funcall func table nil)))
 
+(defun orgtbl-gather-send-defs ()
+  "Gathers a plist of :name, :transform, :params for each destination before
+a radio table."
+  (save-excursion
+    (goto-char (org-table-begin))
+    (let (rtn)
+      (beginning-of-line 0)
+      (while (looking-at "#\\+ORGTBL: *SEND +\\([a-zA-Z0-9_]+\\) +\\([^ \t\r\n]+\\)\\( +.*\\)?")
+	(let ((name (org-no-properties (match-string 1)))
+	      (transform (intern (match-string 2)))
+	      (params (if (match-end 3)
+			  (read (concat "(" (match-string 3) ")")))))
+	  (push (list :name name :transform transform :params params)
+		rtn)
+	  (beginning-of-line 0)))
+      rtn)))
+
+(defun orgtbl-send-replace-tbl (name txt)
+  "Find and replace table NAME with TXT."
+  (save-excursion
+    (goto-char (point-min))
+    (unless (re-search-forward
+	     (concat "BEGIN RECEIVE ORGTBL +" name "\\([ \t]\\|$\\)") nil t)
+      (error "Don't know where to insert translated table"))
+    (goto-char (match-beginning 0))
+    (beginning-of-line 2)
+    (save-excursion
+      (let ((beg (point)))
+	(unless (re-search-forward
+		 (concat "END RECEIVE ORGTBL +" name) nil t)
+	  (error "Cannot find end of insertion region"))
+	(beginning-of-line 1)
+	(delete-region beg (point))))
+    (insert txt "\n")))
+
 (defun orgtbl-send-table (&optional maybe)
   "Send a tranformed version of this table to the receiver position.
 With argument MAYBE, fail quietly if no transformation is defined for
@@ -11669,59 +11704,45 @@ this table."
     (unless (org-at-table-p) (error "Not at a table"))
     ;; when non-interactive, we assume align has just happened.
     (when (interactive-p) (org-table-align))
-    (save-excursion
-      (goto-char (org-table-begin))
-      (beginning-of-line 0)
-      (unless (looking-at "#\\+ORGTBL: *SEND +\\([a-zA-Z0-9_]+\\) +\\([^ \t\r\n]+\\)\\( +.*\\)?")
-	(if maybe
-	    (throw 'exit nil)
-	  (error "Don't know how to transform this table."))))
-    (let* ((name (match-string 1))
-	   beg
-	   (transform (intern (match-string 2)))
-	   (params (if (match-end 3) (read (concat "(" (match-string 3) ")"))))
-	   (skip (plist-get params :skip))
-	   (skipcols (plist-get params :skipcols))
-	   (txt (buffer-substring-no-properties
-		 (org-table-begin) (org-table-end)))
-	   (lines (nthcdr (or skip 0) (org-split-string txt "[ \t]*\n[ \t]*")))
-	   (lines (org-table-clean-before-export lines))
-	   (i0 (if org-table-clean-did-remove-column 2 1))
-	   (table (mapcar
-		   (lambda (x)
-		     (if (string-match org-table-hline-regexp x)
-			 'hline
-		       (org-remove-by-index
-			(org-split-string (org-trim x) "\\s-*|\\s-*")
-			skipcols i0)))
-		   lines))
-	   (fun (if (= i0 2) 'cdr 'identity))
-	   (org-table-last-alignment
-	    (org-remove-by-index (funcall fun org-table-last-alignment)
-				 skipcols i0))
-	   (org-table-last-column-widths
-	    (org-remove-by-index (funcall fun org-table-last-column-widths)
-				 skipcols i0)))
-
-      (unless (fboundp transform)
-	(error "No such transformation function %s" transform))
-      (setq txt (funcall transform table params))
-      ;; Find the insertion place
-      (save-excursion
-	(goto-char (point-min))
-	(unless (re-search-forward
-		 (concat "BEGIN RECEIVE ORGTBL +" name "\\([ \t]\\|$\\)") nil t)
-	  (error "Don't know where to insert translated table"))
-	(goto-char (match-beginning 0))
-	(beginning-of-line 2)
-	(setq beg (point))
-	(unless (re-search-forward (concat "END RECEIVE ORGTBL +" name) nil t)
-	  (error "Cannot find end of insertion region"))
-	(beginning-of-line 1)
-	(delete-region beg (point))
-	(goto-char beg)
-	(insert txt "\n"))
-      (message "Table converted and installed at receiver location"))))
+    (let ((dests (orgtbl-gather-send-defs))
+	  (txt (buffer-substring-no-properties (org-table-begin)
+					       (org-table-end)))
+	  (ntbl 0))
+      (unless dests (if maybe (throw 'exit nil)
+		      (error "Don't know how to transform this table.")))
+      (dolist (dest dests)
+	(let* ((name (plist-get dest :name))
+	       (transform (plist-get dest :transform))
+	       (params (plist-get dest :params))
+	       (skip (plist-get params :skip))
+	       (skipcols (plist-get params :skipcols))
+	       beg
+	       (lines (org-table-clean-before-export
+		       (nthcdr (or skip 0)
+			       (org-split-string txt "[ \t]*\n[ \t]*"))))
+	       (i0 (if org-table-clean-did-remove-column 2 1))
+	       (table (mapcar
+		       (lambda (x)
+			 (if (string-match org-table-hline-regexp x)
+			     'hline
+			   (org-remove-by-index
+			    (org-split-string (org-trim x) "\\s-*|\\s-*")
+			    skipcols i0)))
+		       lines))
+	       (fun (if (= i0 2) 'cdr 'identity))
+	       (org-table-last-alignment
+		(org-remove-by-index (funcall fun org-table-last-alignment)
+				     skipcols i0))
+	       (org-table-last-column-widths
+		(org-remove-by-index (funcall fun org-table-last-column-widths)
+				     skipcols i0))
+	       (txt (if (fboundp transform)
+			(funcall transform table params)
+		      (error "No such transformation function %s" transform))))
+	  (orgtbl-send-replace-tbl name txt))
+	  (setq ntbl (1+ ntbl)))
+      (message "Table converted and installed at %d receiver location%s"
+	       ntbl (if (> ntbl 1) "s" "")))))
 
 (defun org-remove-by-index (list indices &optional i0)
   "Remove the elements in LIST with indices in INDICES.
diff --git a/org.texi b/org.texi
index eae2db0..ac58508 100644
--- a/org.texi
+++ b/org.texi
@@ -8124,8 +8124,10 @@ in the receiver lines. @code{translation_function} is the Lisp function
 that does the translation.  Furthermore, the line can contain a list of
 arguments (alternating key and value) at the end.  The arguments will be
 passed as a property list to the translation function for
-interpretation.  A few standard parameters are already recognized and
-acted upon before the translation function is called:
+interpretation.  Multiple @code{#+ORGTBL: SEND} lines with different
+@code{table_name}s send the table's data to separate destinations.  A
+few standard parameters are already recognized and acted upon before the
+translation function is called:
 
 @table @code
 @item :skip N
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [PATCH] Support multiple destinations for each radio table.
@ 2008-04-16 21:37 Jason Riedy
  0 siblings, 0 replies; 2+ messages in thread
From: Jason Riedy @ 2008-04-16 21:37 UTC (permalink / raw)
  To: emacs-orgmode

You can slice a single table full of calculations in different ways
into separate destinations.  Or you can format the table differently.
There are many fun and exciting possible uses.

A fancier implementation would scan the document *once* for the
set of destinations.  That could help implement another function
to update all destinations from all sources.

Signed-off-by: Jason Riedy <jason@acm.org>
---
  This also can be fetched by pulling 
    git://repo.or.cz/org-mode/ejr.git multitarget-radio-table

 ChangeLog         |   11 +++++
 doc/org.texi      |    6 ++-
 lisp/org-table.el |  127 +++++++++++++++++++++++++++++++----------------------
 3 files changed, 89 insertions(+), 55 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 9ae71a9..8e89686 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2008-04-15  Jason Riedy  <jason@acm.org>
+
+	* lisp/org-table.el (orgtbl-gather-send-defs): New function to
+	gather all the SEND definitions before a table.
+	(orgtbl-send-replace-tbl): New function to find the RECEIVE
+	corresponding to the current name.
+	(orgtbl-send-table): Use the previous two functions and implement
+	multiple destinations for each table.
+
+	* doc/org.texi (Radio tables): Document multiple destinations.
+
 2008-04-15  Carsten Dominik  <dominik@science.uva.nl>
 
 	* lisp/org-agenda.el (org-agenda-columns-show-summaries)
diff --git a/doc/org.texi b/doc/org.texi
index c9eaab9..767830b 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -8397,8 +8397,10 @@ in the receiver lines. @code{translation_function} is the Lisp function
 that does the translation.  Furthermore, the line can contain a list of
 arguments (alternating key and value) at the end.  The arguments will be
 passed as a property list to the translation function for
-interpretation.  A few standard parameters are already recognized and
-acted upon before the translation function is called:
+interpretation.  Multiple @code{#+ORGTBL: SEND} lines with different
+@code{table_name}s send the table's data to separate destinations.  A
+few standard parameters are already recognized and acted upon before the
+translation function is called:
 
 @table @code
 @item :skip N
diff --git a/lisp/org-table.el b/lisp/org-table.el
index 1e1bd85..9193bf0 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -3492,6 +3492,41 @@ overwritten, and the table is not marked as requiring realignment."
 	  (push (> (/ (apply '+ (mapcar (lambda (x) (if (string-match org-table-number-regexp x) 1 0)) column)) maxcol) org-table-number-fraction) org-table-last-alignment))
     (funcall func table nil)))
 
+(defun orgtbl-gather-send-defs ()
+  "Gathers a plist of :name, :transform, :params for each destination before
+a radio table."
+  (save-excursion
+    (goto-char (org-table-begin))
+    (let (rtn)
+      (beginning-of-line 0)
+      (while (looking-at "#\\+ORGTBL: *SEND +\\([a-zA-Z0-9_]+\\) +\\([^ \t\r\n]+\\)\\( +.*\\)?")
+	(let ((name (org-no-properties (match-string 1)))
+	      (transform (intern (match-string 2)))
+	      (params (if (match-end 3)
+			  (read (concat "(" (match-string 3) ")")))))
+	  (push (list :name name :transform transform :params params)
+		rtn)
+	  (beginning-of-line 0)))
+      rtn)))
+
+(defun orgtbl-send-replace-tbl (name txt)
+  "Find and replace table NAME with TXT."
+  (save-excursion
+    (goto-char (point-min))
+    (unless (re-search-forward
+	     (concat "BEGIN RECEIVE ORGTBL +" name "\\([ \t]\\|$\\)") nil t)
+      (error "Don't know where to insert translated table"))
+    (goto-char (match-beginning 0))
+    (beginning-of-line 2)
+    (save-excursion
+      (let ((beg (point)))
+	(unless (re-search-forward
+		 (concat "END RECEIVE ORGTBL +" name) nil t)
+	  (error "Cannot find end of insertion region"))
+	(beginning-of-line 1)
+	(delete-region beg (point))))
+    (insert txt "\n")))
+
 (defun orgtbl-send-table (&optional maybe)
   "Send a tranformed version of this table to the receiver position.
 With argument MAYBE, fail quietly if no transformation is defined for
@@ -3501,59 +3536,45 @@ this table."
     (unless (org-at-table-p) (error "Not at a table"))
     ;; when non-interactive, we assume align has just happened.
     (when (interactive-p) (org-table-align))
-    (save-excursion
-      (goto-char (org-table-begin))
-      (beginning-of-line 0)
-      (unless (looking-at "#\\+ORGTBL: *SEND +\\([a-zA-Z0-9_]+\\) +\\([^ \t\r\n]+\\)\\( +.*\\)?")
-	(if maybe
-	    (throw 'exit nil)
-	  (error "Don't know how to transform this table."))))
-    (let* ((name (match-string 1))
-	   beg
-	   (transform (intern (match-string 2)))
-	   (params (if (match-end 3) (read (concat "(" (match-string 3) ")"))))
-	   (skip (plist-get params :skip))
-	   (skipcols (plist-get params :skipcols))
-	   (txt (buffer-substring-no-properties
-		 (org-table-begin) (org-table-end)))
-	   (lines (nthcdr (or skip 0) (org-split-string txt "[ \t]*\n[ \t]*")))
-	   (lines (org-table-clean-before-export lines))
-	   (i0 (if org-table-clean-did-remove-column 2 1))
-	   (table (mapcar
-		   (lambda (x)
-		     (if (string-match org-table-hline-regexp x)
-			 'hline
-		       (org-remove-by-index
-			(org-split-string (org-trim x) "\\s-*|\\s-*")
-			skipcols i0)))
-		   lines))
-	   (fun (if (= i0 2) 'cdr 'identity))
-	   (org-table-last-alignment
-	    (org-remove-by-index (funcall fun org-table-last-alignment)
-				 skipcols i0))
-	   (org-table-last-column-widths
-	    (org-remove-by-index (funcall fun org-table-last-column-widths)
-				 skipcols i0)))
-
-      (unless (fboundp transform)
-	(error "No such transformation function %s" transform))
-      (setq txt (funcall transform table params))
-      ;; Find the insertion place
-      (save-excursion
-	(goto-char (point-min))
-	(unless (re-search-forward
-		 (concat "BEGIN RECEIVE ORGTBL +" name "\\([ \t]\\|$\\)") nil t)
-	  (error "Don't know where to insert translated table"))
-	(goto-char (match-beginning 0))
-	(beginning-of-line 2)
-	(setq beg (point))
-	(unless (re-search-forward (concat "END RECEIVE ORGTBL +" name) nil t)
-	  (error "Cannot find end of insertion region"))
-	(beginning-of-line 1)
-	(delete-region beg (point))
-	(goto-char beg)
-	(insert txt "\n"))
-      (message "Table converted and installed at receiver location"))))
+    (let ((dests (orgtbl-gather-send-defs))
+	  (txt (buffer-substring-no-properties (org-table-begin)
+					       (org-table-end)))
+	  (ntbl 0))
+      (unless dests (if maybe (throw 'exit nil)
+		      (error "Don't know how to transform this table.")))
+      (dolist (dest dests)
+	(let* ((name (plist-get dest :name))
+	       (transform (plist-get dest :transform))
+	       (params (plist-get dest :params))
+	       (skip (plist-get params :skip))
+	       (skipcols (plist-get params :skipcols))
+	       beg
+	       (lines (org-table-clean-before-export
+		       (nthcdr (or skip 0)
+			       (org-split-string txt "[ \t]*\n[ \t]*"))))
+	       (i0 (if org-table-clean-did-remove-column 2 1))
+	       (table (mapcar
+		       (lambda (x)
+			 (if (string-match org-table-hline-regexp x)
+			     'hline
+			   (org-remove-by-index
+			    (org-split-string (org-trim x) "\\s-*|\\s-*")
+			    skipcols i0)))
+		       lines))
+	       (fun (if (= i0 2) 'cdr 'identity))
+	       (org-table-last-alignment
+		(org-remove-by-index (funcall fun org-table-last-alignment)
+				     skipcols i0))
+	       (org-table-last-column-widths
+		(org-remove-by-index (funcall fun org-table-last-column-widths)
+				     skipcols i0))
+	       (txt (if (fboundp transform)
+			(funcall transform table params)
+		      (error "No such transformation function %s" transform))))
+	  (orgtbl-send-replace-tbl name txt))
+	  (setq ntbl (1+ ntbl)))
+      (message "Table converted and installed at %d receiver location%s"
+	       ntbl (if (> ntbl 1) "s" "")))))
 
 (defun org-remove-by-index (list indices &optional i0)
   "Remove the elements in LIST with indices in INDICES.
-- 
1.5.5.rc1.121.g1594

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2008-04-16 21:37 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-04-16 21:37 [PATCH] Support multiple destinations for each radio table Jason Riedy
  -- strict thread matches above, loose matches on Subject: below --
2008-02-29  5:41 One table, multiple radio targets? Jason Riedy
2008-02-29 10:09 ` Carsten Dominik
2008-03-03  1:46   ` [PATCH] Support multiple destinations for each radio table Jason Riedy

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

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).